/*****************************************************************************
 * common.h: misc common functions
 *****************************************************************************
 * Copyright (C) 2003-2018 x264 project
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Loren Merritt <lorenm@u.washington.edu>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
 *
 * This program is also available under a commercial proprietary license.
 * For more information, contact us at licensing@x264.com.
 *****************************************************************************/

#ifndef X264_COMMON_H
#define X264_COMMON_H

#include "base.h"

/* Macros for templating function calls according to bit depth */
#define x264_template(w) x264_glue3(x264, BIT_DEPTH, w)

/****************************************************************************
 * API Templates
 ****************************************************************************/
#define x264_nal_encode x264_template(nal_encode)
#define x264_encoder_reconfig x264_template(encoder_reconfig)
#define x264_encoder_parameters x264_template(encoder_parameters)
#define x264_encoder_headers x264_template(encoder_headers)
#define x264_encoder_encode x264_template(encoder_encode)
#define x264_encoder_close x264_template(encoder_close)
#define x264_encoder_delayed_frames x264_template(encoder_delayed_frames)
#define x264_encoder_maximum_delayed_frames x264_template(encoder_maximum_delayed_frames)
#define x264_encoder_intra_refresh x264_template(encoder_intra_refresh)
#define x264_encoder_invalidate_reference x264_template(encoder_invalidate_reference)

/* This undef allows to rename the external symbol and force link failure in case
 * of incompatible libraries. Then the define enables templating as above. */
#undef x264_encoder_open
#define x264_encoder_open x264_template(encoder_open)

/****************************************************************************
 * Macros
 ****************************************************************************/
#define X264_PCM_COST (FRAME_SIZE(256*BIT_DEPTH)+16)
#define QP_BD_OFFSET (6*(BIT_DEPTH-8))
#define QP_MAX_SPEC (51+QP_BD_OFFSET)
#define QP_MAX (QP_MAX_SPEC+18)
#define PIXEL_MAX ((1 << BIT_DEPTH)-1)
// arbitrary, but low because SATD scores are 1/4 normal
#define X264_LOOKAHEAD_QP (12+QP_BD_OFFSET)
#define SPEC_QP(x) X264_MIN((x), QP_MAX_SPEC)

#define NALU_OVERHEAD 5 // startcode + NAL type costs 5 bytes per frame
#define FILLER_OVERHEAD (NALU_OVERHEAD+1)
#define SEI_OVERHEAD (NALU_OVERHEAD - (h->param.b_annexb && !h->param.i_avcintra_class && (h->out.i_nal-1)))

#if HAVE_INTERLACED
#   define MB_INTERLACED h->mb.b_interlaced
#   define SLICE_MBAFF h->sh.b_mbaff
#   define PARAM_INTERLACED h->param.b_interlaced
#else
#   define MB_INTERLACED 0
#   define SLICE_MBAFF 0
#   define PARAM_INTERLACED 0
#endif

#ifdef CHROMA_FORMAT
#    define CHROMA_H_SHIFT (CHROMA_FORMAT == CHROMA_420 || CHROMA_FORMAT == CHROMA_422)
#    define CHROMA_V_SHIFT (CHROMA_FORMAT == CHROMA_420)
#else
#    define CHROMA_FORMAT h->sps->i_chroma_format_idc
#    define CHROMA_H_SHIFT h->mb.chroma_h_shift
#    define CHROMA_V_SHIFT h->mb.chroma_v_shift
#endif

#define CHROMA_SIZE(s) (CHROMA_FORMAT ? (s)>>(CHROMA_H_SHIFT+CHROMA_V_SHIFT) : 0)
#define FRAME_SIZE(s) ((s)+2*CHROMA_SIZE(s))
#define CHROMA444 (CHROMA_FORMAT == CHROMA_444)

#if HIGH_BIT_DEPTH
    typedef uint16_t pixel;
    typedef uint64_t pixel4;
    typedef int32_t  dctcoef;
    typedef uint32_t udctcoef;

#   define PIXEL_SPLAT_X4(x) ((x)*0x0001000100010001ULL)
#   define MPIXEL_X4(src) M64(src)
#else
    typedef uint8_t  pixel;
    typedef uint32_t pixel4;
    typedef int16_t  dctcoef;
    typedef uint16_t udctcoef;

#   define PIXEL_SPLAT_X4(x) ((x)*0x01010101U)
#   define MPIXEL_X4(src) M32(src)
#endif

#define CPPIXEL_X4(dst,src) MPIXEL_X4(dst) = MPIXEL_X4(src)

/****************************************************************************
 * Includes
 ****************************************************************************/
#if HAVE_OPENCL
#include "opencl.h"
#endif
#include "cabac.h"
#include "bitstream.h"
#include "set.h"
#include "predict.h"
#include "pixel.h"
#include "mc.h"
#include "frame.h"
#include "dct.h"
#include "quant.h"
#include "threadpool.h"

/****************************************************************************
 * General functions
 ****************************************************************************/

/* log */
#define x264_log x264_template(log)
void x264_log( x264_t *h, int i_level, const char *psz_fmt, ... );

#define x264_cavlc_init x264_template(cavlc_init)
void x264_cavlc_init( x264_t *h );
#define x264_cabac_init x264_template(cabac_init)
void x264_cabac_init( x264_t *h );

static ALWAYS_INLINE pixel x264_clip_pixel( int x )
{
    return ( (x & ~PIXEL_MAX) ? (-x)>>31 & PIXEL_MAX : x );
}

/****************************************************************************
 *
 ****************************************************************************/
typedef struct
{
    x264_sps_t *sps;
    x264_pps_t *pps;

    int i_type;
    // 在 H.264/AVC 规范中，一个宏块是 16 行 16 列像素的数据块，而 i_first_mb 记录了这个 Slice 第一个宏块的编号。通过计算 i_first_mb 和下一个 Slice 的 i_first_mb 的位置，就可以计算出这个 Slice 中包括多少个宏块。这个信息对于编码器和解码器都非常重要。
    int i_first_mb;
    // 最后一个宏块的位置
    int i_last_mb;

    int i_pps_id;

    // i_frame_num也是 x264_slice_header_t 中的一个字段，用来表示当前 Slice 所在的图像在帧序列中的编号。这个编号用于图像解码过程中的参考帧选取和帧的展示顺序
    int i_frame_num;

    // b_mbaff是一个变量，用于指示编码器是否使用场模式。当b_mbaff为1时，表示编码器使用场模式（mbaff模式）
    int b_mbaff;
    // b_field_pic是一个变量，用于指示编码器当前编码的帧是否为场帧
    int b_field_pic;
    // 当b_field_pic为1时，b_bottom_field为0表示当前编码的是场的上半部分，为1表示当前编码的是场的下半部分。
    int b_bottom_field;
    /*i_idr_pic_id是一个变量，表示IDR图像的ID号，IDR图像是H.264视频序列中的一种特殊类型的帧，更确切地说，是图像类型为IDR的I帧。

IDR图像（Instantaneous Decoder Refresh）是视频序列中的关键帧（I帧），它可以作为序列的重新同步点和随机访问点。IDR图像与普通的I帧的不同之处在于，它可以独立地解码并形成完整的图像帧，而其他帧则需要依赖于前面的帧来解码和形成完整的图像帧。

i_idr_pic_id是IDR图像的唯一标识符，在解码过程中，解码器可以使用i_idr_pic_id来识别IDR图像，并利用它重新同步视频序列。*/
    int i_idr_pic_id;   /* -1 if nal_type != 5 */

    /*i_poc是一个变量，表示当前编码的图像的解码顺序号码（POC，Picture Order Count）。编码器使用解码顺序号码来保证图像序列的正确顺序，并且在解码时可以根据解码顺序号码来重组图像序列。解码顺序通常与图像显示顺序不同，在图像显示顺序不同于解码顺序的情况下，解码器必须对编码的POC进行排序和重排序以得到正确的图像显示顺序。

POC是一种计数机制，可以确保不同类型的帧以正确的顺序组成视频序列。对于P帧，POC表示其参考帧的顺序号码；对于B帧，POC表示其前向和后向参考帧的顺序号码。例如，如果一个P帧是第5帧，并且它的参考帧是第3帧，则该P帧的POC为3；如果一个B帧是第10帧，并且它的前向参考帧是第7帧，后向参考帧是第11帧，则该B帧的POC为min(7,11)。

POC机制是H.264标准的一个重要特性，使得编码器和解码器可以实现高效、灵活和可靠的视频编解码。*/
    int i_poc;
    /*i_delta_poc_bottom是一个变量，它用于指示当前编码的B帧的底部场与其参考的底部场之间的POC差值。

在H.264标准中，B帧可以包含一个顶部参考帧和一个底部参考帧，用于预测当前帧。因为在B帧中顶部和底部通常是独立编码的，所以需要分别记录顶部和底部参考帧的POC值。i_delta_poc_bottom就是用于记录当前B帧的底部场与其参考的底部场之间的POC差值。

i_delta_poc_bottom的值可以是正值、负值或0，它表示当前B帧的底部场的POC值与其参考的底部场的POC值之间的差值。这个差值可以用来计算当前B帧的最终顺序号码。*/
    int i_delta_poc_bottom;
    /*i_delta_poc[2]是一个数组，表示当前B帧参考帧的POC差值。在H.264标准中，B帧需要参考其前向和后向两个帧，这个数组就是用于记录这两个帧的POC差值。

具体来说，i_delta_poc[0]表示B帧参考的前向帧（也就是当前帧之前的帧）的POC差值，i_delta_poc[1]表示B帧参考的后向帧（也就是当前帧之后的帧）的POC差值。

B帧通过前向和后向参考帧之间的运动向量来进行预测编码，因此需要记录参考帧的POC差值以确定正确的参考帧和运动矢量。i_delta_poc[0]和i_delta_poc[1]的值可以是正值、负值或0，用于计算当前B帧最终的顺序号码。*/
    int i_delta_poc[2];
    /*i_redundant_pic_cnt是一个变量，表示冗余帧的个数，它只在多码率编码中使用。

在多码率编码中，编码器可能生成多个分辨率或码率的视频流，这些视频流之间可能存在冗余帧，即一些帧在低码率的流中不被编码、传输，而在高码率的流中被编码、传输，这些帧即为冗余帧。冗余帧的存在可以提高重构图像的质量和鲁棒性，因为它提供了额外的参考帧。

i_redundant_pic_cnt表示冗余帧的数量，它可以为0或正整数。如果i_redundant_pic_cnt为0，则表示当前编码的图像不包含冗余帧；如果i_redundant_pic_cnt为正整数n，则表示当前编码的图像包含n个冗余帧。

在解码时，如果当前解码的帧是一个冗余帧，解码器会丢弃该帧，除非解码器缺少其他参考帧或当前帧是最后一帧。*/
    int i_redundant_pic_cnt;

    /*b_direct_spatial_mv_pred是一个变量，用于指示编码器是否要使用空间直接预测运动矢量。

在H.264/AVC标准中，直接预测模式（Direct Prediction Mode）是一种运动矢量预测模式，用于提高P帧和B帧的编码效率和图像质量。在帧间预测过程中，直接预测模式允许编码器使用当前B帧与前向和后向参考帧之间的运动矢量得到当前帧的运动矢量，从而避免了P帧到B帧的参考帧重新解码和重构。

b_direct_spatial_mv_pred为1时，表示编码器可以使用空间直接预测运动矢量。空间直接预测使用前向和后向参考帧之间的运动矢量对当前帧的运动矢量进行预测，而不需要使用其它宏块进行预测。当预测误差较小时，这种预测模式可以有效地减少压缩数据大小并提高编解码的效率。

如果b_direct_spatial_mv_pred为0，则表示编码器不使用空间直接预测运动矢量，并使用其他预测模式。*/
    int b_direct_spatial_mv_pred;

    /*b_num_ref_idx_override是一个变量，用于指示编码器是否覆盖长期参考帧和短期参考帧的默认参考帧索引数量。

在H.264/AVC标准中，长期参考帧和短期参考帧共同作用于帧间预测和运动估计。每个参考帧都有一个默认参考帧索引数量，用于表示它可以提供给编码器的参考帧数量。默认情况下，P帧和B帧的默认参考帧数量分别为1和2。然而，当b_num_ref_idx_override为1时，编码器可以覆盖这些默认值。

当b_num_ref_idx_override为1时，编码器需要设置参考帧的索引数量，来告诉解码器当前帧可以允许使用的参考帧的数量。这可以用于减少参考帧的数量以降低编码的复杂性，或者增加参考帧的数量以提高预测质量和图像质量。

需要注意的是，b_num_ref_idx_override只对P帧和B帧有效。I帧不允许参考帧，因此它没有参考帧索引数量。*/
    int b_num_ref_idx_override;

    /*i_num_ref_idx_l0_active是一个变量，用于指示编码器使用的L0参考帧的数量。

在H.264/AVC标准中，L0参考帧是B帧的前向参考帧。每个B帧都有两个参考帧：一个前向参考帧和一个后向参考帧。i_num_ref_idx_l0_active表示当前B帧可以使用的前向参考帧的数量，它的默认值为2。

当b_num_ref_idx_override为1时，i_num_ref_idx_l0_active可以被编码器覆盖，从而改变可以使用的前向参考帧的数量。

由于B帧的前向和后向参考帧数量的调整可以影响编码器的效率和编码质量，因此H.264/AVC标准中规定了一些语法元素，编码器可以使用这些语法元素来灵活地控制参考帧的数量。这些变量包括i_num_ref_idx_l0_active和i_num_ref_idx_l1_active（后向参考帧数量）。*/
    int i_num_ref_idx_l0_active;
    int i_num_ref_idx_l1_active;
    /*b_ref_pic_list_reordering[2]是一个布尔类型的数组，用于指示编码器是否启用参考帧列表的重新排序。

在H.264/AVC标准中，参考帧列表用于存储当前帧可以引用的参考帧。参考帧列表的顺序通常由编码器根据参考帧的帧间相对顺序和显式设置进行初始化。参考帧列表在帧间预测和运动估计中起着重要的作用，它用于计算运动矢量和预测误差等。

b_ref_pic_list_reordering[0]表示是否启用前向参考帧列表的重新排序，b_ref_pic_list_reordering[1]表示是否启用后向参考帧列表的重新排序。如果b_ref_pic_list_reordering[0]和b_ref_pic_list_reordering[1]都为0，则表示不启用参考帧列表的重新排序。如果b_ref_pic_list_reordering[0]和b_ref_pic_list_reordering[1]有至少一个为1，则表示需要对参考帧列表进行重新排序。

参考帧列表的重新排序可以改变参考帧的顺序，从而影响帧间预测和运动估计的效率和质量。它可以通过一些特定的语法元素（例如ref_pic_list_reordering()和pred_weight_table()）进行控制。*/
    int b_ref_pic_list_reordering[2];
    /*ref_pic_list_order是一个数组，用于存储重新排序后的参考帧顺序。

在H.264/AVC标准中，参考帧列表在帧间预测和运动估计中起着重要的作用。如果允许重新排序参考帧列表，那么编码器必须在编码的比特流中包含重新排序后的参考帧顺序，以便解码器正确地重构图像序列。

ref_pic_list_order是为参考帧顺序重新排序而定义的数组，它存储重新排序后的前向参考帧和后向参考帧的顺序。数组的大小为最大参考帧数量（16）加1。数组的第一项表示参考帧的数量，后面的每一项表示一个参考帧的索引号。例如，如果ref_pic_list_order[0]为2，表示当前帧有两个参考帧（前向和后向参考帧），ref_pic_list_order[1]表示第一个参考帧的索引号，ref_pic_list_order[2]表示第二个参考帧的索引号。

需要注意的是，只有在b_ref_pic_list_reordering[0]和b_ref_pic_list_reordering[1]都为1时，ref_pic_list_order变量才有意义，在其他情况下，它的值没有意义。*/
    struct
    {
        /*在H.264/AVC标准中，参考帧列表的重新排序需要使用两个语法元素：ref_pic_list_mvc_modification()和ref_pic_list_mvc_modification_no_prefix()。其中，ref_pic_list_mvc_modification()使用前缀编码（带idc前缀）来表示参考帧列表的重新排序，ref_pic_list_mvc_modification_no_prefix()则不使用前缀编码，直接在比特流中编码参考帧列表的重新排序。

这两个语法元素都使用相同的参数：idc和arg。idc是一个标识符，用于指示参考帧列表中哪些参考帧被重新排序。arg是一个参数，用于存储被重新排序的参考帧的索引。

具体来说，idc的值可以是0、1或2，它们分别对应着三种不同的指令：

- idc为0时，表示参考帧列表中的参考帧不需要重新排序，arg变量则没有意*/
        int idc;
        int arg;
    } ref_pic_list_order[2][X264_REF_MAX];

    /* P-frame weighting */
    /*x264_slice_header_t中的b_weighted_pred表示编码器是否使用加权预测来预测B帧的像素值。加权预测算法通过对参考帧像素值进行加权平均来预测当前帧像素值，以提高预测精度。当b_weighted_pred为0时，编码器不使用加权预测；当b_weighted_pred为1时，编码器使用加权预测。该参数的默认值为0。*/
    int b_weighted_pred;
    // weight[X264_REF_MAX*2][3]是x264_slice_header_t结构体中的一个二维数组，用于存储加权预测的权重系数值。其中，X264_REF_MAX表示参考帧的最大数目，因为每个参考帧都有一个对应的权重系数。而第二维的大小为3，是因为加权预测算法中需要对Y、Cb、Cr三个分量分别计算加权平均值。因此，weight数组可以表示所有参考帧在所有分量上的权重系数值。其中，数组元素weight[i][j]表示第i个参考帧在第j个分量上的权重系数值。
    x264_weight_t weight[X264_REF_MAX*2][3];

    // 在视频编码中使用基于上下文的运动预测，通常假定前面的已编码帧可用作当前编码帧的参考。i_mmco_remove_from_end指定解码器中刚刚使用的参考帧将从索引结尾处删除的个数。（Memory management control operation regarding reference frames）
    int i_mmco_remove_from_end;
    // 存储mmco数组中MMCO命令的个数。（Memory management control operation regarding reference frames）
    int i_mmco_command_count;
    // 存储关于参考帧的内存管理控制操作(MMCO)命令，用于控制X264如何访问和处理参考帧，包括存储、读取或废弃参考帧。存储了i_mmco_command_count个MMCO命令，具体的数据结构包括两个字段i_difference_of_pic_nums和i_poc。（Memory management control operation regarding reference frames）
    struct /* struct for future expansion */
    {
        int i_difference_of_pic_nums;
        int i_poc;
    } mmco[X264_REF_MAX];

    // CABAC初始CABAC上下文模型索引，指定在语法元素上下文模型（context-adaptive binary arithmetic coding，CABAC）中最初使用的上下文模型设置。这个参数决定了编码器和解码器中CABAC模型的初始化。（Context-adaptive binary arithmetic coding）
    int i_cabac_init_idc;

    // 用于指定当前帧的量化参数QP（quantization parameter）值。QP值越小，量化级别越高，压缩效果会更好，但图像质量会降低。通常，编码器会根据视频源的复杂度和目标比特率来自适应地选择QP值。
    int i_qp;
    // 当前帧的QP值相对于参考帧的QP值的增量。通过设置i_qp_delta，编码器可以更好地控制码率和视频质量。
    int i_qp_delta;
    // 用于标识当前编码是否是SP编码，仅当b_gapless_decision被设置为0时有效。从x264 0.58之后，该变量被废弃，使用b_sps_info标志替代。（SP/SI frame mode）
    int b_sp_for_swidth;
    // 当QP值较大时，对高频系数进行较强的量化，这会导致某些区域的细节产生严重失真。i_qs_delta可用于将增量应用于量化参数，该参数只应用于高频系数。默认设置为0，表示不使用Quantization scaling参数。
    int i_qs_delta;

    /* deblocking filter */
    // 禁用去块滤波器的标志值，可选值为0、1、2。0表示不禁用去块滤波器，1表示只滤波内部跳过块（内部无法利用预测的宏块），2表示禁用去块滤波器。
    // 不等于1，则要滤波
    int i_disable_deblocking_filter_idc;
    // 即A值，去块滤波器中，设置Alpha参数的偏移量。该值表明的是在(Alpha)两侧的加法值。
    int i_alpha_c0_offset;
    // 即B值，去块滤波器中，设置Beta参数的偏移量。该值表明的是在(Beta)两侧的加法值。
    int i_beta_offset;

} x264_slice_header_t;

// x264_lookahead_t结构体是x264编码器实现中关键的一个结构体，它用于实现预测编码（Look-ahead encoding）算法，即在编码当前帧时，利用即将到来的帧的信息来提高压缩效率。
typedef struct x264_lookahead_t
{
    // 一个volatile类型的8位无符号整数，表示是否退出线程。volatile关键字表示该字段可能被异步更新，需要以原子方式读取或写入。
    volatile uint8_t              b_exit_thread;
    // 一个8位无符号整数，表示线程是否处于活动状态。
    uint8_t                       b_thread_active;
    // 该字段是一个8位无符号整数，表示是否分析关键帧。如果该字段为1，表示现在处理的是关键帧，需要进行关键帧的预测计算；如果该字段为0，表示现在处理的是非关键帧，可以跳过关键帧的预测计算。
    uint8_t                       b_analyse_keyframe;
    // 该字段是一个整数，表示上一个关键帧的位置。该字段用于在预测编码算法中确定下一个关键帧的位置。
    int                           i_last_keyframe;
    // 切片类型的长度是指切片类型信息在每个NAL单元（网络提取单元）头部中的码字位数。在执行预测编码时，x264编码器会根据切片类型的长度来选择正确的类型，并将结果写入NAL单元头部。正确选择切片类型可以提高编码效率和视频质量。
    // 该字段是一个整数，表示切片类型的长度。切片类型在预测编码中用于确定关键帧的位置，并且对编码效率有影响。
    int                           i_slicetype_length;
    // 该字段是一个指向x264_frame_t类型的指针，表示上一个非B帧。在预测编码中，B帧通常需要引用前后多个帧的信息，而非B帧只需要引用前面的帧信息，因此需要在编码器中保存上一个非B帧的信息。
    x264_frame_t                  *last_nonb;
    // 该字段是一个x264_pthread_t类型的结构体，表示线程句柄。该字段用于启动和停止线程。
    x264_pthread_t                thread_handle;
    // 该字段是一个x264_sync_frame_list_t类型的结构体，表示输入缓冲区。该缓冲区用于保存即将到来的帧的信息，以便预测算法使用。
    x264_sync_frame_list_t        ifbuf;
    // 该字段是一个x264_sync_frame_list_t类型的结构体，表示下一个缓冲区。在多线程处理中，需要使用多个缓冲区以保证并发性和数据一致性。
    x264_sync_frame_list_t        next;
    // 该字段是一个x264_sync_frame_list_t类型的结构体，表示输出缓冲区。该缓冲区用于保存预测编码算法中生成的码流数据。
    x264_sync_frame_list_t        ofbuf;
} x264_lookahead_t;

typedef struct x264_ratecontrol_t   x264_ratecontrol_t;

typedef struct x264_left_table_t
{
    // x264_left_table_t 中的 intra[4] 是一个长度为 4 的 uint8_t 数组，用于表示每个 4x4 块是否采用帧内预测的标志位。
    uint8_t intra[4];
    /*x264_left_table_t 中的 nnz[4] 是一个长度为 4 的 uint8_t 数组，用于表示每个 4x4 块中非零系数的数目。

在 H.264 中，采用零块跳过原则来减少数据量。如果一个 4x4 块中所有系数都为 0，那么该块可以完全跳过不进行编码，从而减少编码数据量。因此，x264_left_table_t 中的 nnz[4] 可以在编码过程中判断一个 4x4 块是否全为 0，从而进行适当的优化。

同时，x264_left_table_t 中的 nnz_chroma[4] 也是类似的变量，表示每个 4x4 块中色度分量中非零系数的数目。在编码过程中，对于色度分量与亮度分量的编码可以采取不同的策略进行优化。*/
    uint8_t nnz[4];
    uint8_t nnz_chroma[4];
    /*x264_left_table_t 中的 mv[4] 是一个长度为 4 的 uint8_t 数组，用于表示每个 4x4 块中运动矢量的索引值。

在 H.264 的编码中，运动矢量可以理解为当前块与参考帧之间的位移量，用于描述当前块在参考帧中的位置。运动矢量的编码方式有多种，但是对于一些编码模式下，当前块与某个参考帧之间的运动矢量可以通过预设规则简单推导出来。对于这种情况下的块，x264_left_table_t 中的 mv[4] 就用一个索引值表示即可，通过查找对应表格得到实际的运动矢量。

在编码过程中，用一个索引值来表示运动矢量可以减少数据量，从而提高编码效率。*/
    uint8_t mv[4];
    /*类型为 uint8_t 数组，长度为 4，表示每个 4x4 块与参考帧的索引值。类似于运动矢量，参考帧的选择规则也可以通过预设规则来简化，用一个索引值表示即可，然后根据规则获取实际参考帧。*/
    uint8_t ref[4];
} x264_left_table_t;

/* Current frame stats */
typedef struct
{
    /* MV bits (MV+Ref+Block Type) */
    // i_mv_bits变量记录运动矢量（MV）、参考帧和块类型的比特数，这些编码信息对于视频压缩来说非常重要。
    int i_mv_bits;
    //  i_tex_bits变量记录离散余弦变换（DCT）系数的比特数，DCT系数是视频压缩中的重要编码信息。
    /* Texture bits (DCT coefs) */
    int i_tex_bits;
    /* ? */
    // 记录其他类型的比特数，具体用途没有给出。
    int i_misc_bits;
    /* MB type counts */
    //  i_mb_count变量记录宏块编码类型的数量，包括I帧，P帧，B帧，SKIP帧以及8x8DCT的P帧和B帧等19种编码类型。
    int i_mb_count[19];
    // 记录I帧的宏块数。
    int i_mb_count_i;
    // 记录P帧的宏块数。
    int i_mb_count_p;
    // 记录SKIP帧的宏块数。
    int i_mb_count_skip;
    // 记录使用8x8DCT的P帧和B帧的宏块数。
    int i_mb_count_8x8dct[2];
    //  i_mb_count_ref变量记录参考帧的使用情况和类型，这些信息主要用于运动估计和反向运动补偿过程中。
    int i_mb_count_ref[2][X264_REF_MAX*2];
    // i_mb_partition变量记录宏块分割类型的数量，包括16x16和16x8等17种分割类型。
    int i_mb_partition[17];
    //  i_mb_cbp变量记录宏块的色度块编码模式的数量，一共6种模式。
    int i_mb_cbp[6];
    // i_mb_pred_mode变量记录16x16宏块的预测模式的数量，一共4种预测模式，每个模式下有13种子模式。
    int i_mb_pred_mode[4][13];
    // 记录场编码的使用情况，具体包括3种场编码类型。
    int i_mb_field[3];
    /* Adaptive direct mv pred */
    //  i_direct_score变量记录直接模式下的得分，包括前向和后向直接模式。
    int i_direct_score[2];
    /* Metrics */
    // i_ssd变量记录均方差（SSD）的值，以及3种亮度、色度分量的SSD值，用于衡量帧间编码的失真。
    int64_t i_ssd[3];
    // f_ssim变量记录结构相似度（SSIM）的值，刻画了原始帧和编码帧之间的结构相似度。
    double f_ssim;
    // i_ssim_cnt变量记录SSIM的计算次数，用于平均SSIM值的计算。
    int i_ssim_cnt;
} x264_frame_stat_t;

struct x264_t
{
    /* encoder parameters */
    x264_param_t    param;

    /*x264_t是x264编码器的主要结构体，它包含了x264编码器的所有参数、状态和函数指针等信息。其中thread[X264_THREAD_MAX+1]是一个指向线程结构体数组的指针，它的作用是用来管理编码器中的所有线程。

具体来说，x264编码器是一个多线程程序，它会根据系统的CPU核心数自动创建多个编码线程来进行视频编码。其中，thread[0]表示主线程，在编码过程中主要用来处理一些初始化和收尾工作。而thread[1]到thread[X264_THREAD_MAX]表示编码线程，它们负责执行实际的编码任务。使用多线程可以充分利用系统的CPU资源，提高编码器的效率和速度。

需要注意的是，线程数不能超过X264_THREAD_MAX的最大值。在x264_t结构体中，thread数组的大小为(X264_THREAD_MAX+1)，这是因为在创建编码线程时，还需要一个额外的线程来处理一些任务调度和同步等工作。*/
    x264_t          *thread[X264_THREAD_MAX+1];
    /*x264_t结构体中的lookahead_thread[X264_LOOKAHEAD_THREAD_MAX]是一个指针数组，它用于管理x264编码器中预测线程的信息。预测线程是用于帧间预测分析的线程，它的作用是在编码过程中提前对下一帧视频进行帧间预测，以尽可能地提高编码效率和压缩率。

在这个指针数组中，每个元素表示一个预测线程的指针，最大值为X264_LOOKAHEAD_THREAD_MAX。与编码线程类似，预测线程的数量也会根据系统的CPU核心数自动调整，以最大程度地利用系统资源。

需要注意的是，预测线程并不是必需的，可以通过x264_param_t结构体中的b_deblocking启用或禁用它们。如果禁用了预测线程，x264编码器将不会使用任何预测信息，而直接对每一帧进行编码。*/
    x264_t          *lookahead_thread[X264_LOOKAHEAD_THREAD_MAX];
    // b_thread_active是一个布尔类型的变量，用于表示x264编码器是否正在运行多线程编码过程中的子线程。如果b_thread_active的值为1，则表示子线程正在活跃状态；如果b_thread_active的值为0，则表示子线程没有处于活跃状态。
    int             b_thread_active;
    /*在x264_t结构体中，i_thread_phase是一个整型变量，用于表示当前x264编码器运行多线程编码时所处的阶段。i_thread_phase的值在0~2之间：

- 如果值为0，则表示编码器不在多线程模式下。
- 如果值为1，则表示编码器正在进行分析阶段，此阶段涉及到多线程的并行处理。
- 如果值为2，则表示编码器正在进行编码阶段，即将数据压缩为比特流的过程，此阶段也会使用多线程并行处理。*/
// 下一帧需要选择的线程
    int             i_thread_phase; /* which thread to use for the next frame */
    /*在x264_t结构体中，i_thread_idx是一个整型变量，用于表示当前x264编码器的编码线程 ID。在多线程模式下，该变量的值为0到n-1，表示编码器的每个线程都有一个唯一的编号，用于区分线程之间的不同任务。如果当前编码器不在多线程模式下，i_thread_idx的值始终为零。*/
    int             i_thread_idx;   /* which thread this is */
    /*在x264_t结构体中，i_threadslice_start是一个整型变量，用于表示当前编码线程开始编码的MB块在图像中的起始位置。在多线程模式下，当一帧图像被拆成多个MB块时，每个编码线程负责编码其中一部分MB块。由于MB块的处理顺序不固定，因此需要使用i_threadslice_start变量记录当前编码线程开始处理的MB块位置，以便进行正确的回调和MB块的状态同步。在单线程模式下，i_threadslice_start的值为0。*/
    int             i_threadslice_start; /* first row in this thread slice */
    /*在x264_t结构体中，i_threadslice_end是一个整型变量，用于表示当前编码线程结束编码的MB块在图像中的位置，即i_threadslice_start到i_threadslice_end之间的MB块由该编码线程负责编码。i_threadslice_end的值在多线程模式下由编码器动态计算，根据编码器运行过程中不同线程之间的任务分配和负载均衡进行灵活调整，以确保每个线程处理的MB块数量相对均衡。在单线程模式下，i_threadslice_start和i_threadslice_end的值相等，均为0。*/
    int             i_threadslice_end; /* row after the end of this thread slice */
    /*在x264_t结构体中，i_threadslice_pass是一个整型变量，用于表示当前编码线程在多线程模式下的编码任务扫描状态。i_threadslice_pass的值在0~2之间：

- 如果i_threadslice_pass的值为0，则表示编码器当前正处于ENCODER_PSY rd-opt分析阶段。
- 如果i_threadslice_pass的值为1，则表示编码器当前正处于ENCODER_ME多线程运动估计阶段。
- 如果i_threadslice_pass的值为2，则表示编码器当前正处于ENCODER_ANALYSE ME分析,Texture Decision Soft限制阶段。*/
    int             i_threadslice_pass; /* which pass of encoding we are on */
    /*在x264_t结构体中，threadpool是一个结构体指针，指向一个用于多线程编码的线程池。线程池是由多个线程组成的线程集合，用于可靠地管理多线程编码过程中的任务分配、负载均衡和同步等问题。在x264中，线程池的实现基于pthread库，通过构建多个线程来实现多线程编码，进而提高编码性能和并行处理效率。通过使用线程池，x264可以更好地利用多核CPU资源，提高编码速度和效率。*/
    x264_threadpool_t *threadpool;
    x264_threadpool_t *lookaheadpool;
    x264_pthread_mutex_t mutex;
    x264_pthread_cond_t cv;

    /* bitstream output */
    struct
    {
        /*在x264_t结构体中，i_nal是一个整型变量，用于记录当前帧的NAL单元数。NAL（Network Abstraction Layer）单元是H.264/AVC视频编码标准中的基本编码单元，用于进行视频编码和传输。在x264编码器中，每个NAL单元对应一个码流中的数据包，有助于实现视频压缩、传输和解码等基本功能。i_nal变量用于记录当前帧生成的NAL单元数，以便进行码流划分和数据传输。i_nal的值与当前帧中包含的编码数据大小和NAL单元的数量成正比。*/
        int         i_nal;
        /*在x264_t结构体中，i_nals_allocated是一个整型变量，用于记录为当前帧分配NAL单元的数量。NAL单元是H.264/AVC视频编码标准中的基本编码单元，用于进行视频编码和传输。在x264编码器中，为了确保每个NAL单元都能完整传输，需要根据NAL单元的大小和数量动态分配数据缓冲区，存储编码数据。当编码器开始编码新的一帧时，会根据NAL单元数量估计预分配数据缓冲区大小，并使用i_nals_allocated变量记录分配的NAL单元数量。如果i_nals_allocated的值小于实际需要的NAL单元数量，编码器将自动调整数据缓冲区大小，以确保编码数据的完整性。*/
        int         i_nals_allocated;
        /*在x264_t结构体中，nal是一个指向NALUnit数组的指针，存储的是当前帧编码后生成的NAL单元数据。NAL单元是H.264/AVC视频编码标准中的基本编码单元，用于进行视频编码和传输。在x264编码器中，每个NAL单元对应一个码流中的数据包，有助于实现视频压缩、传输和解码等基本功能。在x264_t结构体中，nal指针指向一个包含当前帧所有NAL单元的数组，在编码完成后被传递回给调用者，用于进行码流的存储、传输和输出等操作。其中，NALUnit结构体包含了该NAL单元的相关信息，如类型、大小和数据等。*/
        x264_nal_t  *nal;
        /*在x264_t结构体中，i_bitstream是一个整型变量，用于记录当前帧编码后的比特流数据大小。比特流是H.264/AVC视频编码标准中的输出数据，表示压缩后的视频编码数据。在x264编码器中，每个编码过程都将生成一个比特流数据作为输出结果。i_bitstream记录了当前帧编码后生成的比特流数据大小，它与码率、分辨率、帧率等因素相关。可以使用该值对编码效果进行评估，也可以用于码流带宽控制、码率自适应等应用场景的调整。*/
        int         i_bitstream;    /* size of p_bitstream */
        /*在x264_t结构体中，p_bitstream是一个无符号字符型指针，指向当前帧编码后的比特流数据。比特流是H.264/AVC视频编码标准中的输出数据，表示压缩后的视频编码数据。在x264编码器中，每个编码过程都将生成一个比特流数据作为输出结果。p_bitstream指向当前帧编码后的比特流数据，可以用于进行码流的存储、传输和输出等操作。比特流的大小由i_bitstream记录，p_bitstream的有效长度也受i_bitstream的限制。*/
        uint8_t     *p_bitstream;   /* will hold data for all nal */
        /*在x264_t结构体中，bs是一个结构体指针，指向了一个Bitstream结构体，该结构体存储当前帧的比特流数据。比特流是H.264/AVC视频编码标准中的输出数据，表示压缩后的视频编码数据。在x264编码器中，每个编码过程都将生成一个比特流数据作为输出结果。bs指针所指向的Bitstream结构体管理了比特流数据的缓存和数据读写操作，嵌入了各种处理函数，可供系统用户进行使用。bs结构体的常用函数包括写入比特流数据、写入NALU头部、字节对齐操作、获取比特流数据缓存、判断缓存是否为空、刷新比特流数据、释放缓存等。使用Bitstream结构体，可以方便地处理和管理比特流数据。*/
        bs_t        bs;
    } out;

    /*在x264_t结构体中，nal_buffer是一个数组，用于存储NAL单元数据。NAL单元是H.264/AVC视频编码标准中的基本编码单元，用于进行视频编码和传输。在x264编码器中，在编码过程中会将编码后的NAL单元数据存储在nal_buffer数组中，待所有NAL单元编码完成后，将这些数据拼接起来即可得到完整的比特流数据。nal_buffer的大小需要根据实际情况进行设置，以确保足够存储所有NAL单元数据。x264编码器使用nal_buffer对NAL单元数据进行统一管理和存储，从而方便地进行码流输出、传输、存储和解码。*/
    uint8_t *nal_buffer;
    int      nal_buffer_size;
    /*在x264_t结构体中，reconfig_h是一个函数指针，用于重新配置编码器中x264_param_t结构体中的h结构体变量，并重新初始化编码器。在调用reconfig_h函数前，需要先将x264_param_t结构体中的h结构体变量进行修改，修改完成后再调用reconfig_h函数进行编码器的重新初始化。该函数可以帮助应用程序在编码过程中动态调整编码参数和配置选项，以实现更好的编码质量和性能。在函数调用过程中，编码器会根据新的参数重新初始化输出缓存区、线程池、比特流数和相关状态等信息，以确保编码器能够顺利地运行并输出正确的编码数据。*/
    x264_t          *reconfig_h;
    /*在x264_t结构体中，reconfig是一个整型变量，用于标识是否需要在编码器的下一轮运行中重新配置编码器的x264_param_t结构体。如果reconfig的值为1，则表示需要重新配置编码器，否则需要继续使用旧的编码参数和配置选项进行编码。在编码器运行的过程中，应用程序可以通过修改x264_param_t结构体中的相关选项，设置新的编码参数，然后将reconfig变量设为1，以通知编码器在下一轮运行时重新进行参数配置。这种动态调整的方式可以帮助应用程序在不停止编码器的情况下改变编码参数和调整编码效果，从而更好地应对动态编码场景的需求。*/
    int             reconfig;

    /**** thread synchronization starts here ****/

    /* frame number/poc */
    /*表示已经编码过的帧数，它与i_frame_num的区别在于，如果在编码过程中有一些帧因为一些原因被丢弃或者重编码，那么i_frame的计数就会比i_frame_num低。*/
    int             i_frame;
    /*表示当前帧的帧编号，是一个递增的整数。*/
    int             i_frame_num;
    /*表示正在被编码的不同帧数，如果启用了线程切片，则为1，否则为0。在启用线程切片的情况下，i_thread_frames代表着可以同时处理的不同帧数，可以提高编码效率。*/
    int             i_thread_frames; /* Number of different frames being encoded by threads;
                                      * 1 when sliced-threads is on. */
    int             i_nal_type;
    int             i_nal_ref_idc;

    /*i_disp_fields是x264_t结构体中的一个字段，表示当前帧的显示域，即用于表示当前帧包含哪些颜色域。具体解释如下：

在视频编码中，颜色信息通常是以许多小块（所谓的像素块）的方式进行编码的。每个像素块表示一个特定的区域，并包含其像素的颜色信息。一个视频帧中的像素块通常被分为两个部分，称为“上半场”和“下半场”。在一些情况下，还可能使用其他方法来表示这些颜色信息，如场和帧等。

i_disp_fields中的值反映当前帧包含哪些颜色信息，可以是：

- 0：表示该帧不包含任何颜色信息，当视频的帧率很低，或者是黑白视频时，通常会采用这种方式。
- 1：表示当前帧只包含“上半场”的颜色信息，即该帧是一个“场”的视频帧。
- 2：表示当前帧只包含“下半场”的颜色信息，也是一个“场”的视频帧。
- 3：表示当前帧同时包含“上半场”和“下半场”的颜色信息，即该帧是一个“帧”的视频帧。

此外，在某些编码模式下，i_disp_fields还可能用于表示冗余信息的数量。*/
    int64_t         i_disp_fields;  /* Number of displayed fields (both coded and implied via pic_struct) */
    /*i_disp_fields_last_frame是x264_t结构中的一个字段，表示上一帧的显示域类型。具体解释如下：

在视频编码中，颜色信息通常是以许多小块（所谓的像素块）的方式进行编码的。一个视频帧中的像素块通常被分为两个部分，称为“上半场”和“下半场”。在一些情况下，还可能使用其他方法来表示这些颜色信息，如场和帧等。

i_disp_fields_last_frame表示上一帧（也就是上一个编码的视频帧）的显示域类型，如果上一帧是一个“场”的视频帧，那么它的值为1或2，如果上一帧是一个“帧”的视频帧，那么它的值为3，如果上一帧不包含颜色信息，那么它的值为0。它的作用是用于指导当前帧的编码，以便编码器可以尽可能地利用相邻帧之间的相似性，从而提高压缩效率。*/
    int             i_disp_fields_last_frame;
    /*i_prev_duration是x264_t结构体中的一个字段，表示前一帧（previous frame）的持续时间，即前一个I帧到当前帧中间间隔的帧数。它通常用于控制编码器的码率（bitrate）以及处理视频流中的缓冲区（buffer）。

在视频编码中，为了保证视频流的稳定性和流畅度，需要对码率进行控制，通常采用的方法是通过控制帧速率（frame rate）来控制码率，即根据视频中每一帧的比特率、帧率等参数来确定视频的码率。另一方面，如果视频流中缓冲区的大小超出一定范围，可能会导致播放卡顿或者花屏等问题，因此也需要对缓冲区进行控制。

i_prev_duration可以用于计算当前帧的码率，方法是将前一帧到当前帧中间间隔的帧数（即i_prev_duration）与前一帧的比特率相乘，从而得到当前帧的比特率。例如，如果前一帧的比特率为1000kbps，前一帧和当前帧中间间隔了5帧，那么当前帧的比特率就是5000kbps。这个值可以用于控制编码器的码率，从而控制视频的质量和文件大小。*/
    int64_t         i_prev_duration; /* Duration of previous frame */
    /*i_coded_fields是x264_t结构体中的一个字段，表示当前帧已编码的颜色域类型，即表示在当前帧中哪些颜色域已经被编码了。它可以是以下值之一：

- 0：表示当前帧不包含任何颜色信息，或者该信息尚未被编码。
- 1：表示当前帧已经编码了“上半场”的颜色信息。
- 2：表示当前帧已经编码了“下半场”的颜色信息。
- 3：表示当前帧已经编码了“上半场”和“下半场”的颜色信息，即该帧已经编码完成了。

i_coded_fields的作用是提供给编码器一个指示，告诉编码器哪些颜色信息已经被编码了，哪些颜色信息还需要被编码。这有助于编码器优化数据压缩，提高编码效率。同时，它也可以用于解码器来解码视频数据，以确保解码器可以正确地处理和呈现每一帧。*/
    int64_t         i_coded_fields; /* Number of coded fields (both coded and implied via pic_struct) */
    /*i_cpb_delay是x264_t结构体中的一个字段，表示编码器中的码率控制缓冲区大小（CPB）延迟。在视频编码中，CPB用于控制码率和视频质量，以确保输出码率平稳，并使视频质量保持在预期水平。CPB的大小和延迟也对码率控制和视频质量具有重要影响。

i_cpb_delay表示编码器中的码率控制缓冲区的延迟，单位是毫秒。CPB的延迟可以通过改变i_cpb_delay的值来进行调整。延迟越大，码率控制的精度就越高，输出码率就越平稳，但延迟也会增加。因此，在使用i_cpb_delay时需要平衡码率控制和延迟之间的折衷。

i_cpb_delay还可以与其他编码设置一起使用，如码率（bitrate）和最大码率（max bitrate），以进一步控制编码器输出的码率和视频质量。*/
    int64_t         i_cpb_delay;    /* Equal to number of fields preceding this field
                                     * since last buffering_period SEI */
    /*i_coded_fields_lookahead是x264_t结构体中的一个字段，表示编码器中用于码率控制的lookahead缓冲区已编码的颜色域类型。具体来说，它表示预测下一帧颜色类型的值，以便帮助编码器做出更准确的码率控制决策。

在视频编码中，码率控制是非常重要的，它可以帮助确保输出的视频流具有适当的码率和视频质量。x264编码器实现了一种名为lookahead的技术，通过前瞻缓冲区先预测一些未来帧的信息，从而更准确地确定码率控制策略。i_coded_fields_lookahead字段用于记录前瞻缓冲区中预测下一帧的颜色类型，以帮助编码器进行准确计算。

例如，在前瞻缓冲区中，预测下一帧是“场”帧，那么i_coded_fields_lookahead的值将是1或2，表示预期下一帧的颜色类型。这个值可以用于调整编码器的码率控制策略，从而提高编码质量。*/
    int64_t         i_coded_fields_lookahead; /* Use separate counters for lookahead */
    /*i_cpb_delay_lookahead是x264_t结构体中的一个字段，表示编码器中码率控制缓冲区已编码的lookahead帧所需要的延迟时间。它的值通常会大于i_cpb_delay，因为编码器需要预测未来帧的信息以计算码率控制策略，预测信息的缓冲区会引入额外的延迟。

i_cpb_delay和i_cpb_delay_lookahead这两个值都是用来进行码率控制的，它们的使用可以帮助编码器更加准确地计算视频的平均码率，并确保输出的码率和视频质量符合预期。由于使用了lookahead技术，i_cpb_delay_lookahead的值会更大，这可以帮助编码器更好地预测未来帧的信息，从而获得更好的编码效果。*/
    int64_t         i_cpb_delay_lookahead;
    /*i_cpb_delay_pir_offset是x264_t结构体中的一个字段，表示在场景（scene）切换点处使用的码率控制延迟偏移量，用于提高视频的编码质量。在一些情况下，特别是在场景切换点处，视频的复杂程度会发生变化，以至于原有的码率控制策略无法满足要求，导致编码质量下降。i_cpb_delay_pir_offset的作用就是在场景切换点处调整码率控制延迟，以提高编码器的性能和质量。

具体来说，i_cpb_delay_pir_offset会对原有的延迟值（即i_cpb_delay和i_cpb_delay_lookahead）进行调整，以确保在场景切换点处码率控制能够更加准确和精细。在场景切换点之前，编码器会根据预测的场景复杂度调整码率控制策略，以获得更好的编码效果。在场景切换点之后，编码器将根据i_cpb_delay_pir_offset的值调整延迟，使码率控制更加准确。*/
    int64_t         i_cpb_delay_pir_offset;
    /*i_cpb_delay_pir_offset_next是x264_t结构体中的一个字段，表示在下一个场景（scene）切换点处使用的码率控制延迟偏移量，用于提高视频的编码质量。与i_cpb_delay_pir_offset类似，它的作用是帮助编码器在场景切换点处调整码率控制延迟，以获得更好的编码质量。

视频的场景切换点通常是指场景的切换或者视频内容发生重大变化的地方，这些地方可能需要更高的码率控制精度来保证编码质量。i_cpb_delay_pir_offset_next表示在下一个场景切换点处编码器需要增加的码率控制缓冲区的延迟偏移量。通过使用这个字段，编码器可以在下一个场景切换点之前预测场景的复杂度，并且根据预测结果调整码率控制策略，以获得更好的编码效果。*/
    int64_t         i_cpb_delay_pir_offset_next;

    /*b_queued_intra_refresh是x264_t结构体中的一个布尔值字段，表示是否使用队列刷新（queued refresh）技术来进行自适应帧内刷新（intra refresh）编码。在视频编码中，帧内刷新是一种常用的技术，它会周期性地进行自适应重编码，以保障视频质量和稳定性。

队列刷新是一种改进的自适应帧内刷新技术，它可以帮助减少I帧的数量，从而提高编码效率。通过使用队列刷新，编码器可以将自适应帧内刷新的编码任务分割成多个小的任务，并将这些任务排入队列中，在编码过程中来逐个处理，从而减少I帧的数量。

b_queued_intra_refresh字段用于控制是否启用队列刷新技术，如果设置为true，编码器就可以使用队列刷新来调整自适应帧内刷新的方式，从而提高编码效率。*/
    int             b_queued_intra_refresh;
    int64_t         i_last_idr_pts;
    /*i_idr_pic_id是x264_t结构体中的一个字段，表示当前图像的IDR帧ID（IDR picture ID）。在视频编码中，IDR帧是一种关键帧（keyframe），它可以帮助解码器重新同步，恢复视频的正常播放。

在H.264/AVC标准中，每个IDR帧都有一个唯一的IDR帧ID，用于标识该帧。i_idr_pic_id字段记录当前帧的IDR帧ID。这个值在视频流中可以用于同步和恢复，以及参考帧的选择、重要性的计算等其他相关任务。*/
    int             i_idr_pic_id;

    /* quantization matrix for decoding, [cqm][qp%6][coef] */
    /*这是x264中的一个指针数组，每个元素指向一个16x16的int类型的二维数组（共4个）。

这些数组在解码过程中，用于恢复出码流中的量化系数，从而得到解码后的像素值。

其中，dequant4_mf是一个指针数组，它包含了4个元素，每个元素都是指向一个16x16的二维数组的指针。每个二维数组保存了一个4x4的量化矩阵，用于将DCT变换后的系数进行量化处理。这样可以达到压缩码流的效果。

在解码过程中，需要把码流中的量化系数解码出来，通过这些量化矩阵进行反量化，得到原始的DCT系数，然后再进行IDCT变换，得到解码后的像素值。*/
    int             (*dequant4_mf[4])[16];   /* [4][6][16] */
    /*这是x264中的一个指针数组，每个元素指向一个64x64的int类型的二维数组（共4个）。

这些数组同样在解码过程中使用，用于解码码流中的量化系数，从而得到解码后的像素值。

dequant8_mf也是一个指针数组，它包含了4个元素，每个元素都是指向一个64x64的二维数组的指针。每个二维数组保存了一个8x8的量化矩阵，用于将DCT变换后的系数进行量化处理。与dequant4_mf相比，它的量化矩阵更大，因此可以更细粒度地控制压缩效果。

在解码过程中，需要使用这些量化矩阵把码流中的量化系数反量化回来，得到原始的DCT系数，然后再进行IDCT变换，得到解码后的像素值，从而还原出原始的图像。*/
    int             (*dequant8_mf[4])[64];   /* [4][6][64] */
    /* quantization matrix for trellis, [cqm][qp][coef] */
    /*这也是x264中的一个指针数组，每个元素指向一个16x16的int类型的二维数组（共4个）。

这些数组也与解码过程相关，用于对码流中经过量化处理过的DCT系数进行反量化。

unquant4_mf同样是一个指针数组，包含4个元素，每个元素都指向一个16x16的二维数组，保存了一个4x4的反量化矩阵。

在解码过程中，需要使用这些反量化矩阵来把解码出来的DCT系数反量化，得到原始的DCT系数，然后再进行IDCT变换，得到解码后的像素值，从而还原出原始的图像。

与dequant4_mf不同的是，unquant4_mf保存的是反量化矩阵，而dequant4_mf保存的是量化矩阵。它们的作用正好相反。*/
    int             (*unquant4_mf[4])[16];   /* [4][QP_MAX_SPEC+1][16] */
    int             (*unquant8_mf[4])[64];   /* [4][QP_MAX_SPEC+1][64] */
    /* quantization matrix for deadzone */
    /*这是x264中的一个指针数组，每个元素指向一个16x16的udctcoef类型的二维数组（共4个）。

这些数组同样与编码和解码过程中的DCT变换相关，用于保存经过量化处理后的DCT系数。

quant4_mf同样是一个指针数组，包含4个元素，每个元素都指向一个16x16的二维数组，保存了一个4x4的量化矩阵。

在编码过程中，需要使用这些量化矩阵来把DCT系数进行量化，从而实现对图像数据的压缩。在解码过程中，则需要使用对应的反量化矩阵（例如前面提到的unquant4_mf）来对压缩后的DCT系数进行反量化。

udctcoef是x264中定义的一个结构体，用于保存DCT系数的无损表示形式。它包含了三个成员变量，分别是level、run、last，分别表示DCT系数的大小、零块的长度、以及一次变换过程中最后一个非零系数的位置。quant4_mf保存的正是这样的DCT系数。*/
    udctcoef        (*quant4_mf[4])[16];     /* [4][QP_MAX_SPEC+1][16] */
    udctcoef        (*quant8_mf[4])[64];     /* [4][QP_MAX_SPEC+1][64] */
    /*这也是x264中的一个指针数组，每个元素指向一个16x16的udctcoef类型的二维数组（共4个）。

和quant4_mf类似，这些数组同样用于DCT系数的量化处理，但代表的是加上bias后的量化矩阵。

quant4_bias同样是一个指针数组，包含4个元素，每个元素都指向一个16x16的二维数组，保存了一个4x4的加上bias后的量化矩阵。

在编码过程中，对DCT系数进行量化时，可能会加上一个bias偏置，以控制压缩效果。quant4_bias就是保存了这个加上bias后的量化矩阵。同样需要注意的是，quant4_bias保存的是经过量化处理后的DCT系数，而不是保存加上bias后的量化矩阵本身。

在解码过程中，则需要使用对应的反量化矩阵（例如前面提到的unquant4_mf）来反量化经过量化处理后的DCT系数，得到原始的DCT系数。然后再把bias减回去，最后进行IDCT变换，得到解码后的像素值，从而还原出原始的图像。*/
    udctcoef        (*quant4_bias[4])[16];   /* [4][QP_MAX_SPEC+1][16] */
    /*udctcoef (*quant8_bias[4])[64]和udctcoef (*quant4_bias[4])[16]是两个指向三维数组的指针变量。它们的主要区别在于数组的维度和大小，以及它们的作用。

- quant8_bias指向一个四维数组，它包含了4个色度分量（chroma component）的8x8块的偏差（bias）。每个块用64个无符号整型（uint32_t）表示。该数组用于在x264_t中对8x8块进行量化（quantization）时应用偏差，用来优化压缩效率。

- quant4_bias指向一个四维数组，它包含了4个色度分量的4x4块的偏差。每个块用16个无符号整型表示。该数组用于x264_t中对4x4块进行量化时应用偏差，用来优化压缩效率。

因此，尽管它们都是指向三维数组的指针变量，但它们指向的数组的大小和作用是不同的。而通过修改这些偏差值，可以改善编码器的效率和输出质量。*/
    udctcoef        (*quant8_bias[4])[64];   /* [4][QP_MAX_SPEC+1][64] */
    /*这也是x264中的一个指针数组，与quant4_bias类似，每个元素指向一个16x16的udctcoef类型的二维数组（共4个）。

quant4_bias0同样是一个指针数组，包含4个元素，每个元素都指向一个16x16的二维数组，保存了一个4x4的加上bias并将右下角系数调整为0后的量化矩阵。

在编码过程中，为了进一步控制压缩效果，可能会对加上bias后的量化矩阵进行调整。例如，可以通过将右下角系数调整为0来消除一些高频信号，从而达到更好的压缩效果。

quant4_bias0保存的就是经过此类处理后的量化矩阵，需要使用它来对DCT系数进行量化。同样需要注意的是，quant4_bias0保存的是经过量化处理后的DCT系数，而不是保存加上bias并调整后的量化矩阵本身。

在解码过程中，同样需要使用对应的反量化矩阵（例如前面提到的unquant4_mf）来反量化经过量化处理后的DCT系数，并把bias和调整恢复回去，最后进行IDCT变换，得到解码后的像素值，从而还原出原始的图像。*/
    udctcoef        (*quant4_bias0[4])[16];  /* [4][QP_MAX_SPEC+1][16] */
    udctcoef        (*quant8_bias0[4])[64];  /* [4][QP_MAX_SPEC+1][64] */
    /*udctcoef (*nr_offset_emergency)[4][64]是一个指向三维数组的指针。这个三维数组中包含4个元素，每个元素是一个64个无符号整型（uint32_t）的一维数组。这个指针是用于在x264_t中设置紧急降噪（noise reduction）的偏移量（offset）的变量。每个元素表示一个色度分量（chroma component），即UV平面和alpha平面。可以通过设置该变量来更好地控制编码器的输出质量和细节处理。*/
    udctcoef        (*nr_offset_emergency)[4][64];

    /* mv/ref/mode cost arrays. */
    /*uint16_t *cost_mv[QP_MAX+1]是一个指针数组，在x264中用于存储运动矢量（motion vector）的成本（cost）。其中，QP_MAX是一个常量，表示最大量化参数（quantization parameter）的值。

运动矢量是一个向量，用于描述视频图像中物体在两个时间点之间的移动。在视频编码中，需要对每个块（block）进行运动估计（motion estimation），然后根据运动矢量来预测未来的图像帧。成本值表示了运动矢量的好坏，即它对预测误差的贡献，成本值越大表示预测误差越小，运动矢量越合适。

在x264中，cost_mv数组用于存储运动矢量的成本值，它有QP_MAX+1个元素，对应不同的量化参数。每个元素是一个指向uint16_t类型的指针，指向一个保存成本值的数组。通过修改这些成本值，可以改进运动估计的效率和预测准确度，从而提高编码器的质量和性能。*/
    uint16_t *cost_mv[QP_MAX+1];
    /*uint16_t *cost_mv_fpel[QP_MAX+1][4]是一个三维指针数组，用于保存亚像素级别（fractional-pixel level）的运动矢量成本（cost）。其中，QP_MAX是一个常量，表示最大量化参数（quantization parameter）的值，第二个维度是4，表示不同的像素级别，具体包括1/4、1/2、3/4和全像素，第三个维度对应的是运动矢量的方向，其中0表示水平运动，1表示垂直运动，2表示左上到右下的对角线运动和3表示右上到左下的对角线运动。

亚像素级别是指在像素级别上的小于1像素的运动矢量。在运动估计中，为了更准确地描述物体的运动，可以将运动向量分解为一个全像素运动向量和一个亚像素运动向量。然后根据不同的像素级别来估计亚像素级别运动的成本，即cost_mv_fpel数组所保存的值。

通过修改这些成本值，可以优化运动估计算法，提高编码器的性能和图像质量。*/
    uint16_t *cost_mv_fpel[QP_MAX+1][4];

    struct
    {
        /*uint16_t ref[QP_MAX+1][3][33]是一个三维数组，在x264中用于存储宏块（macroblock）参考图像的像素值。其中，QP_MAX是一个常量，表示最大量化参数（quantization parameter）的值，第二个维度3表示不同的参考图像类型，其中索引为0表示前向预测（forward prediction），1表示双向预测（bidirectional prediction），2表示后向预测（backward prediction），第三个维度33表示参考图像的不同分辨率的像素大小。

在H.264/AVC中，编码过程是以宏块为基本单位进行的。每个宏块都可以用不同的预测模式来估计相邻图像块的像素值，以减少编码时的数据冗余。参考图像是编码过程中被用作参考的图像。x264编码器支持多种不同类型的参考图像，分别用于不同的预测模式。这些参考图像的像素值存储在ref数组中，在编码过程中可以直接使用，无需再次解码。

通过修改ref数组中的值，可以改进预测模式的算法，提高编码器的性能和图像质量。*/
/*在H.264/AVC视频编码中，参考图像可以用多个分辨率的图像来表示，这些分辨率通常与编码过程中使用的多个空间预测过程有关。在x264中，参考图像和当前宏块的像素的匹配通常是在多个分辨率上进行的。因此，ref数组中的33表示参考图像的不同分辨率的像素大小，即用33个整数来表示每个分辨率的参考图像的宽度和高度。其中前16个表示水平和垂直方向上的亚像素大小（fractional-pixel size），后17个则是正常像素大小（luma/chroma samples per line）。在x264中，使用这些不同分辨率的参考图像来进行多级别的运动估计（motion estimation），同时也可用于多级别的运动补偿（motion compensation）。*/
        uint16_t ref[QP_MAX+1][3][33];
        /*uint16_t i4x4_mode[QP_MAX+1][17]是一个二维数组，在x264中用于存储I帧（Intra-coded frame）下的每个4x4宏块（macroblock）可能采用的预测模式（prediction mode）。其中，QP_MAX是一个常量，表示最大量化参数（quantization parameter）的值，第二个维度17表示不同的预测模式，其中包括4种无方向模式（DC、左、上、横竖均值模式），9种带方向模式（纵向、横向、左上到右下斜向、右上到左下斜向）和4种带随机扰动的模式。

I帧是指只使用帧内预测（intra prediction）来编码的视频帧，其中每个宏块都是与自身像素值进行预测。在H.264/AVC编码过程中，每个4x4宏块都需要选择一个最佳的预测模式和相应的重构像素值。i4x4_mode数组记录了每个宏块可以采用的所有预测模式，可以根据输入图像的特征和量化参数等条件来选择最佳的预测模式。

通过修改i4x4_mode数组中的值，可以优化预测模式的选择算法，提高编码器的性能和图像质量。*/
        uint16_t i4x4_mode[QP_MAX+1][17];
    } *cost_table;

    /*const uint8_t *chroma_qp_table是一个指向常量的无符号整型（uint8_t）数组，在x264_t结构体中用于存储不同色度分量（chroma component）的量化参数（quantization parameter）的数据，即chroma QP table。在H.264/AVC编码中，每个块（block）都有一个针对不同色度分量的量化参数。chroma QP table中可存储多个采样比（sampling ratio）下的色度分量的量化参数，可使编码器在不同采样比下的编码能力更加优秀并且更加适合于真实世界中的视频编码。

使用chroma QP table时，可以通过修改和替换数组中的元素，来优化编码器的输出质量和性能。例如，增加一种特定采样比的数量，可以提高编码器对该采样比的适应性和性能；或者修改特定索引处量化参数的值，可以提高编码器对某些色度分量的编码性能。*/
    const uint8_t   *chroma_qp_table; /* includes both the nonlinear luma->chroma mapping and chroma_qp_offset */

    /* Slice header */
    x264_slice_header_t sh;

    /* SPS / PPS */
    x264_sps_t      sps[1];
    x264_pps_t      pps[1];

    /* Slice header backup, for SEI_DEC_REF_PIC_MARKING */
    /*int b_sh_backup是一个保存编码器视频首部（sequence header）信息备份（backup）的布尔型（bool）变量。在x264编码器中，编码器会首先生成视频首部，该首部包含了关于编码码率、分辨率、帧率、图像格式等基本信息。这个首部是在整个视频编码过程中都需要使用的，因此在编码器编码过程中，需要保证视频首部的正确性和完整性。

为了保证视频首部的完整性，编码器在编码过程中会将视频首部信息备份到内存中，并在编码结束后再将备份的首部信息写回。b_sh_backup变量用于保存是否备份过首部信息的标志。如果b_sh_backup的值为非零值，则表示编码器已经完成了首部信息的备份。该变量的作用是让编码器在多线程并发的情况下，确保只有一个线程完成了首部信息的备份。这样可以避免多个线程同时备份导致冲突，从而保证编码器的正确性和稳定性。*/
    int b_sh_backup;
    /*x264_slice_header_t sh_backup是一个x264_slice_header_t类型的变量，在x264编码器中用于保存视频切片（slice）头信息的备份（backup）。切片是视频帧的一个分割单元，可以将一个视频帧分割成多个切片进行编码，从而提高编码器的效率和性能。

在编码器编码过程中，需要保证切片头信息的正确性和完整性，并且为了多线程并发处理，也需要保证每个线程都有正确的切片头信息。因此，在编码器启动时，需要备份切片头信息并保存到sh_backup变量中。在编码过程中，每个编码线程都可以访问该变量来获取正确的切片头信息。在编码结束时，需要将备份的切片头信息还原回去。

通过使用sh_backup变量，可以避免切片头信息被多个线程同时访问和修改，从而确保并发编码过程中的正确性和稳定性。*/
/*x264_t是x264库的主体结构体，x264_slice_header_t是x264库中的数据结构，表示一个编码帧的片（slice）的头信息。x264_slice_header_t sh和x264_slice_header_t sh_backup的区别在于，sh表示当前编码的片的头信息，而sh_backup则表示上一个编码的片的头信息备份，用于后续的参考。

在x264编码过程中，每个帧被划分为多个片，每个片都可以独立编码。x264_slice_header_t sh记录了当前编码片的头信息，包括片的位置、大小、类型、QP值等，用于控制编码器的行为。而sh_backup在参考帧的预测和MV（运动向量）搜索等过程中，会被用来参考先前编码的片的头信息，以提高编码效率和质量。*/
    x264_slice_header_t sh_backup;

    /* cabac context */
    /*x264_cabac_t cabac; 是x264库中的一个结构体，表示x264的上下文自适应二元上下文。这个结构体包含了一组二元状态（0/1），用于表示H.264/AVC视频编码器的上下文模型。而上下文模型是一种统计方法，用于描述二元数据在不同情况下出现的概率。在x264中，cabac主要用于实现CABAC（基于上下文的自适应二元算术编码）算法，是视频编码中过程复杂度较高的部分之一。

CABAC算法是H.264/AVC视频编码器的一种算法，将二元数据作为条件，并依据当前二元数据前面的若干二元数据来决定二元数据出现的概率和表达的大小。它采用前面二元数据出现概率统计的方法，将编码统计的结果存放在上下文模型中，一般称之为「上下文」。这样，在编码时就不需要每个二元数据都进行编码，而是根据当前的上下文从预先统计的分布中选取最优二元输出，从而降低压缩后文件的大小。*/
    x264_cabac_t    cabac;

    /*x264_t中的frames是用于管理视频编码和解码中的帧缓存的数据结构。它存储了当前正在编码的帧，以及未使用的编码和解码帧。此外，它还包含了参考帧和已分配的解码图像缓存中的帧数的最大值。通过管理帧缓存，x264_t中的frames可以跟踪和控制每个帧的编码顺序和处理时间，以便生成输出视频流。同时，frames还可以跟踪参考帧，以提高视频压缩的效率和质量。*/
    struct
    {
        /* Frames to be encoded (whose types have been decided) */
        // 表示当前正在编码的帧。
        x264_frame_t **current;
        /* Unused frames: 0 = fenc, 1 = fdec */
        // 没有被使用的帧
        // 表示未使用的帧。数组长度为2，其中0代表编码帧，1代表解码帧。
        x264_frame_t **unused[2];

        /* Unused blank frames (for duplicates) */
        // 表示未使用的空白帧，用于复制。
        x264_frame_t **blank_unused;

        /* frames used for reference + sentinels */
        // 参考帧
        // 表示参考帧，长度为X264_REF_MAX+2。
        x264_frame_t *reference[X264_REF_MAX+2];

        // 表示最后一个关键帧的帧数。
        int i_last_keyframe;       /* Frame number of the last keyframe */
        // 表示最后一个IDR帧的帧数（不是RP）。
        int i_last_idr;            /* Frame number of the last IDR (not RP)*/
        // 表示上一个开放式GOP的I帧的POC。此值仅在该I帧和下一个P或I帧之间分配，否则为-1。
        int i_poc_last_open_gop;   /* Poc of the I frame of the last open-gop. The value
                                    * is only assigned during the period between that
                                    * I frame and the next P or I frame, else -1 */

        // 表示已接受的输入帧数。
        int i_input;    /* Number of input frames already accepted */

        // 表示已分配到解码图像缓存中的帧数的最大值。
        int i_max_dpb;  /* Number of frames allocated in the decoded picture buffer */
        // 表示参考列表0中的最大帧数。
        int i_max_ref0;
        // 表示参考列表1中的最大帧数。
        int i_max_ref1;
        // 表示为B帧重新排序缓冲的帧数。
        int i_delay;    /* Number of frames buffered for B reordering */
        // I、P帧之间，多少B帧
        // 以下两个变量全局搜索后，发现，没有什么用
        int     i_bframe_delay;
        // 间隔i_bframe_delay帧的时间戳
        // 表示I、P帧之间最大的B帧时间戳。
        int64_t i_bframe_delay_time;
        // 第一帧的pts
        int64_t i_first_pts;
        // 表示前两帧重新排序后的时间戳。
        int64_t i_prev_reordered_pts[2];
        // 最后一帧的时间戳
        int64_t i_largest_pts;
        // 倒数第二帧的时间戳
        int64_t i_second_largest_pts;
        // 是否使用低分辨率
        // 表示是否使用1/2分辨率的亮度层。
        int b_have_lowres;  /* Whether 1/2 resolution luma planes are being used */
        // 表示是否使用8x8子区域的均值误差调整。
        int b_have_sub8x8_esa;
    } frames;

    /* current frame being encoded */
    // 待编码帧
    x264_frame_t    *fenc;

    /* frame being reconstructed */
    // 解码帧
    x264_frame_t    *fdec;

    /* references lists */
    // 在x264_t中，i_ref[2]表示参考图像列表中的两个参考帧的索引。这些参考帧用于当前待编码的帧的运动估计和预测。i_ref[0]是最近的参考帧的索引，i_ref[1]是前一个参考帧的索引。
    int             i_ref[2];
    /*在x264编码器中，x264_frame_t *fref[2][X264_REF_MAX+3]用于存储参考帧的指针数组。它有两个维度，第一维是用于存储 P 帧和 B 帧的参考帧，第二维则是对参考帧的索引进行操作，将索引分为以下几类：

1. 0-30，对应正常的帧，也就是说 fref[0][i] 存储 P 帧或 B 帧的第 i 个参考帧，fref[1][i] 则为后向参考帧；
2. 31，对应场模式时的完整参考帧；
3. 32，对应场模式时的前场参考帧；
4. 33，对应场模式时的后场参考帧。

它的作用是用于在编码器中快速访问已经编码的参考帧，实现帧内预测和帧间预测等编码任务。由于视频编码需要大量的参考帧，因此使用一个指针数组来管理参考帧，可以提高编码速度和效率。*/
    x264_frame_t    *fref[2][X264_REF_MAX+3];
    /*在x264编码器中，x264_frame_t *fref_nearest[2] 是一个数组，用于存储 P 帧或 B 帧的最近参考帧，在编码器中使用它来进行运动估计和运动补偿操作，以便实现帧间预测。

该数组共有两个元素，每个元素都是一个指向 x264_frame_t 结构体的指针。第一个元素是指向 P 帧的最近参考帧，第二个元素是指向 B 帧的最近前向参考帧。最近参考帧是根据当前帧的时间戳和参考帧的时间戳相对距离来确定的。

在帧间预测中，编码器使用最近参考帧来预测当前待编码帧的像素值，并将差异编码为运动矢量和残差图像。由于最近参考帧通常是相邻的帧，因此使用它进行预测可以减少编码器运算量，提高编码效率。*/
    x264_frame_t    *fref_nearest[2];
    // 是否有前向和后向参考帧？？
    /*在 x264 编码器中，int b_ref_reorder[2] 用于存储 B 帧参考帧的排序标志。它是一个大小为 2 的整型数组，其中 b_ref_reorder[0] 表示是否需要对前向参考帧进行重新排序，b_ref_reorder[1] 表示是否需要对后向参考帧进行重新排序。

在 B 帧编码中，编码器通常需要使用两个参考帧进行预测，即前向参考帧和后向参考帧。由于编码器需要使用运动矢量来表示当前帧相对于参考帧的位移，因此参考帧的顺序很重要。如果参考帧的顺序不正确，将会导致编码器的性能下降。

通过设置 b_ref_reorder 来指定是否需要对参考帧进行重新排序来使帧间预测更为准确，从而提高编码效率和视频质量。如果一个参考帧使用次数较多，则可以将其排序提前，从而减少昂贵的存储器读/写操作。*/
    int             b_ref_reorder[2];

    /* hrd */
    /*在 H.264/AVC 视频编码中，x264 编码器采用了 H.264/AVC 标准的码流缓冲区控制策略，即使用初始缓冲区删除延迟 (initial_cpb_removal_delay) 参数来控制编码输出的码流大小。

initial_cpb_removal_delay 是一个整数值，用于表示下一个编码图像填充到编码器中时，需要等待的时间，这个时间的单位是码流缓冲区中的时间刻度。初始缓冲区删除延迟与码率控制参数紧密相关，它的值将影响到编码器实际输出的码率。

具体地说，码率控制器在编码过程中会根据视频源特点、码率控制的设定、QP 码率和扩展数据等来实时计算码流缓冲区填充程度，进而根据缓冲区的状态控制码率的输出。因此，初始缓冲区删除延迟也就充当了一个码率控制器的一个参数，可以帮助控制码率。而缓冲区的填充程度是用当前时间和最后一个访问时间的差来计算的，也就是说，如果初始缓冲区删除延迟越小，那么码流输出的速度就越快，码率也就越高，所输出的码流也会越大。*/
    int initial_cpb_removal_delay;
    /*x264 编码器中的 initial_cpb_removal_delay_offset 是初始缓冲区删除延迟的偏移量，是码率控制器的一个参数。

它是一个整数值，单位为码流缓冲区时间刻度。初始缓冲区删除延迟偏移量的设置可以通过调整编码器生成的码流输出速率来控制码流缓冲区中填充的程度，以达到不同的码率输出设定。如果 initial_cpb_removal_delay_offset 的值为正数，那么将导致初始缓冲区的填充程度降低，码流输出速度加快，从而导致编码后的码流质量下降；如果其值为负数，则导致码率输出速度降低，输出的码率和码流质量则会得到提升。

在码率控制参数 QP 的初始化时，x264 编码器会根据初始缓冲区删除延迟偏移量和码率控制的设定来确定实际的输出码率。*/
    int initial_cpb_removal_delay_offset;
    /*i_reordered_pts_delay 是 x264 编码器的一个变量，表示 GOP 内已经编码的帧的最大解码时间戳的差值。

具体而言，i_reordered_pts_delay 存储的是上一个 GOP 内编码过程中最后一个帧的解码时间戳 i_reordered_pts 的数值。在编码当前 GOP 的前一帧时，需要计算当前帧的解码时间戳与 i_reordered_pts_delay 的差值来得到当前帧的 pts (显示时间戳)，从而保证视频播放的顺序正确，不出现帧播放顺序混乱的情况。因此，i_reordered_pts_delay 对于编码器是非常重要的变量之一。*/
    int64_t i_reordered_pts_delay;

    /* Current MB DCT coeffs */
    struct
    {
        /*在 x264 编码器中，ALIGNED_64 是一个宏定义，用于将变量对齐到 64 字节边界，以提高内存访问速度和效率。dctcoef luma16x16_dc[3][16] 是一个二维数组，表示亮度帧的 16x16 的 DC 系数矩阵。这个 DC 系数矩阵在离散余弦变换（DCT）中计算得到，由于 H.264/AVC 规范规定 I 帧可以直接编码 DCT 的结果，因此编码器通常将此数组的值编码为比特流输出，用于视频数据的压缩。

这个数组被定义为 ALIGNED_64，表示它要求在内存中对齐到 64 字节边界。这使得变量的存储位置在内存中的地址必须是 64 的整数倍，因为现代计算机体系结构中的64字节对齐可以提高内存访问速度，尤其是在读取大量数据时。因此，ALIGN_64 宏定义通常被用于提高关键数据的处理性能，而这个 DC 系数矩阵可以视为编码器中的一个关键数据。*/
        ALIGNED_64( dctcoef luma16x16_dc[3][16] );
        /*ALIGNED_16 是一个宏定义，它告诉编译器将变量对齐到 16 字节边界，以提高内存访问速度。在 x264 编码器中，dctcoef chroma_dc[2][8] 是一个二维数组，用于存储色度分量的 DC 系数。它是一个大小为 2x8 的二维数组，包含了两行和 8 列，表示了两个颜色通道（U 和 V）的 DC 系数。*/
        /*在 H.264/AVC 中，亮度分量的 DC 系数矩阵大小为 16x16，而色度分量的 DC 系数矩阵大小为 8x8。这是由于 H.264/AVC 规范中规定的，4:2:0 采样下，一个色度像素只需要一个 DC 系数进行编码，而一个亮度像素则需要 4 个 DC 系数进行编码。*/
        ALIGNED_16( dctcoef chroma_dc[2][8] );
        // FIXME share memory?
        /*在 x264 编码器中，luma8x8[12][64] 表示 12 个 8x8 的子块中的所有的 64 个亮度块的 DCT 系数，这些系数用于计算残差块。而 luma4x4[16*3][16] 表示在 H.264/AVC 中 16 个 4x4 的子块是亮度和色度分量都能使用到的，这个数组存储了用于编码的这些子块的 16 个 DCT 系数。注意到这个数组的第一维大小是 16*3，也就是说它存储了 16 个 4x4 的块分别来自一个亮度块和两个色度块的 DCT 系数。*/
        // luma8x8[4*3][8*8]，4个8x8
        ALIGNED_64( dctcoef luma8x8[12][64] );
        // luma4x4[16*3][4*4],16个4x4
        ALIGNED_64( dctcoef luma4x4[16*3][16] );
    } dct;

    /* MB table and cache for current frame/mb */
    struct
    {
        /*在 H.264/AVC 规范中，宏块（macroblock）是视频编码的基本单元，一个宏块通常包含一个 16x16 的亮度块和两个 8x8 的色度块。i_mb_width 是 x264 编码器中的一个参数，它表示一帧视频中一行的宏块数量。它的值的计算公式为：

i_mb_width = ( i_width + 15 ) / 16

其中，i_width 表示一帧视频的宽度。因此，i_mb_width 表示了一帧视频中横向所包含的宏块个数。*/
        int     i_mb_width;
        // 纵向所包含的宏块个数
        int     i_mb_height;
        // 当前帧包含的宏块数
        int     i_mb_count;                 /* number of mbs in a frame */

        /* Chroma subsampling */
        // 在x264_t中，int chroma_h_shift是指用于计算色度（chroma）数据的水平偏移量。它用于将色度取样比特（chroma sample bit）的位置从像素的中心移动生成色度子样本。更具体地说，chroma_h_shift指示每个4:2:0格式中U和V子采样点相对于Y亮度样本的偏移量。例如，对于4:2:0格式，U和V子采样点的偏移量通常为1，因此chroma_h_shift为1。
        int     chroma_h_shift;
        // 垂直偏移量
        int     chroma_v_shift;

        /* Strides */
        // i_mb_stride是一个宏块（macroblocks）行所占的字节数。在x264中，宏块通常是16x16像素的块，即一个宏块通常是256个像素。因此，i_mb_stride就表示每行的字节数，以确保在处理宏块时不会越界。
        int     i_mb_stride;
        // i_b8_stride是一个8x8块的字节数，在许多x264内部函数中都使用这个值作为每行的跨度，以确保在处理8x8块时不会越界。i_b8_stride还被用于控制在编码8x8分块时每行的偏移量。
        int     i_b8_stride;
        // i_b4_stride是一个4x4块的字节数，在许多子模块函数中都使用这个值作为每行的跨度，以确保在处理4x4块时不会越界。i_b4_stride还被用于控制在编码4x4分块时每行的偏移量。
        int     i_b4_stride;
        /*在x264_t结构体中，int left_b8[2]表示当前宏块（MB）左边的两个8x8分块（b8），该数组的长度为2。

在H.264/AVC视频编码标准中，图像块被划分为一系列的宏块，每个宏块通常是16x16像素的大小。宏块又被划分为4个8x8分块（b8）。left_b8数组用于存储当前宏块左侧的8x8块的信息。

具体来说，left_b8[0]保存左侧宏块的左侧8x8分块的信息，left_b8[1]保存左侧宏块的右侧8x8分块的信息。这些信息可以用来进行运动估计，以提高编码效率。*/
        int     left_b8[2];
        /*在x264_t结构体中，int left_b4[2]表示当前宏块（MB）左侧的两个4x4分块（b4），该数组的长度为2。

与8x8分块类似，H.264/AVC视频编码标准中的宏块也被分为4个4x4分块（b4）。left_b4数组用于存储当前宏块左侧的4x4分块的信息。

具体来说，left_b4[0]保存左侧宏块的左侧4x4分块的信息，left_b4[1]保存左侧宏块的右侧4x4分块的信息。这些信息可以用于进行运动估计，以提高编码效率。*/
        int     left_b4[2];

        /* Current index */
        // 当前宏块所在的水平位置，以宏块为单位。
        int     i_mb_x;
        // 当前宏块所在的垂直位置，以宏块为单位。
        int     i_mb_y;
        // 当前宏块在水平和垂直方向的位置，以宏块为单位。按从上到下，从左到右的方向递增
        int     i_mb_xy;
        // 当前宏块子块（b8）在水平和垂直方向的位置，以8x8块为单位。
        int     i_b8_xy;
        // 当前宏块子块（b4）在水平和垂直方向的位置，以4x4块为单位。
        int     i_b4_xy;

        /* Search parameters */
        /*在x264_t结构体中，int i_me_method是用于运动估计（Motion Estimation，ME）的方法。x264使用运动估计来寻找最佳的运动向量，以便在视频编码过程中优化动态图像的压缩。

i_me_method的值用于指定x264在运动估计过程中使用的算法方法，主要包括以下选项：

- X264_ME_DIA：使用钻石搜索算法（Diamond Search Algorithm）来寻找最佳运动向量。
- X264_ME_HEX：使用六边形搜索算法（Full Search Hexagon Diamond Algorithm）来寻找最佳运动向量。
- X264_ME_UMH：使用umh搜索算法（Uneven Multi-Hexagon-grid Sarch）来寻找最佳运动向量。
- X264_ME_ESA：使用全像素ESA搜索算法（Exhaustive Search Algorithm）来寻找最佳运动向量。
- X264_ME_TESA：使用子像素的全像素ESA搜索算法来寻找最佳运动向量。

这些算法根据搜索范围的大小、速度、算法复杂度等不同因素进行优化，也可以通过自定义算法来满足特定的编码需求。*/
        int     i_me_method;
        /*在x264_t结构体中，int i_subpel_refine用于指定在运动估计中所使用的子像素插值精度，以使得运动向量更加准确。具体来说，它表示每个像素所使用的子像素插值点数。

- i_subpel_refine为0表示使用整像素运动估计，即只使用像素级别来计算运动向量。
- i_subpel_refine为1表示使用1组4点子像素插值，即在像素之间使用4个孔径来进行插值。
- i_subpel_refine为2表示使用2组4点子像素插值，即在像素之间使用8个孔径来进行插值。
- i_subpel_refine为3表示使用4组4点子像素插值，即在像素之间使用16个孔径来进行插值。

所使用的子像素点的数量越多，运动向量越精确，但计算量也越大，编码速度越慢。因此，i_subpel_refine的值需要平衡编码质量和速度之间的关系。*/
        int     i_subpel_refine;
        // 表示是否使用色度（chroma）运动估计。
        int     b_chroma_me;
        /*在x264_t结构体中，int b_trellis用于开启或关闭trellis量化算法。

trellis量化是一种基于暴力搜索的优化技术，可以在保持压缩率不变的情况下，提高视频编码的质量，特别是在低比特率时。它通过迭代处理来优化量化过程，并尝试通过修剪不必要的编码枝来找到最优解，以产生更高质量，更好压缩的视频。

当b_trellis为1时，x264会自动开启trellis量化算法。当b_trellis为0时，x264将只应用标准量化算法。

需要注意的是，开启trellis量化算法会增加编码的时间，因此在编码速度对你的应用程序非常重要时，需要谨慎选择是否使用。*/
        int     b_trellis;
        // 是否开启噪声减少（Noise Reduction）功能，以消除视频中的噪声和瑕疵。它可以在编码过程中使用滤波器算法来减少噪声，并提高编码质量。
        int     b_noise_reduction;
        /*在x264_t结构体中，int b_dct_decimate用于控制是否开启DCT降采样功能。

DCT降采样是一种在压缩视频方面非常常见的技术，它通过减小帧中的高频分量来减少数据量。它可以帮助提高视频编码的压缩比和编码效率。

当b_dct_decimate为1时，x264会启用DCT降采样功能。当b_dct_decimate为0时，则不会应用任何DCT降采样算法。*/
        int     b_dct_decimate;
        /*在x264_t结构体中，int i_psy_rd用于控制x264在编码过程中使用的心理视觉优化算法（Psycho-Visual Optimization Algorithm）的级别。

心理视觉优化算法是一种通过模拟人类视觉系统对视频质量感知的方式来优化视频编码质量的方法。在x264中，这个算法通过对视频编码过程中的各个参数进行调整，以获得最佳的视觉效果和最优的压缩率。

i_psy_rd的值越高，心理视觉优化算法的级别就越高，对影像特征的调整也就越精细。但高级别的算法也会带来更大的计算开销和编码时间。在大部分情况下，x264默认的级别就可以获得很好的视频质量和压缩效果，因此对于一般应用，可能没有必要修改i_psy_rd的值。*/
        int     i_psy_rd; /* Psy RD strength--fixed point value*/
        /*在x264_t结构体中，int i_psy_trellis用于控制心理视觉优化算法（Psycho-Visual Optimization Algorithm）和trellis量化算法的结合方式。

心理视觉优化算法可以根据人类视觉系统的响应特征来优化编码参数，从而提高视频编码的视觉质量。trellis量化算法则可以在保持压缩率不变的情况下，提升视频编码的质量。

i_psy_trellis的取值范围为0到6，它控制了心理视觉优化算法和trellis算法之间的权衡：

- i_psy_trellis为0时，将只应用标准量化算法，即不使用trellis算法和心理视觉优化算法。
- i_psy_trellis大于0时，x264将使用trellis算法结合心理视觉优化算法来优化视频编码质量，i_psy_trellis越大，心理视觉优化算法和trellis量化算法的结合将越紧密，视频编码的质量将越高。

需要注意的是，在使用心理视觉优化算法和trellis算法时，会增加计算量和编码时间，因此需要使用合理的设置来平衡视频编码的压缩效率和编码时间。*/
        int     i_psy_trellis; /* Psy trellis strength--fixed point value*/

        // x264_t中的int b_interlaced表示视频是否是交织扫描格式。如果b_interlaced为0，则表示视频为逐行扫描（progressive scan）格式；如果b_interlaced为1，则表示视频为交织扫描（interlaced scan）格式
        int     b_interlaced;
        // 在x264_t中，int b_adaptive_mbaff表示是否使用自适应宏块帧/场（Adaptive Macroblock Affinity）编码模式。当b_adaptive_mbaff为0时，表示不使用自适应宏块帧/场编码；当b_adaptive_mbaff为1时，表示使用自适应宏块帧/场编码。自适应宏块帧/场编码是一种视频编码技术，能够在编码过程中根据当前图像的运动情况自适应地选择宏块帧/场编码模式，从而提高编码效率和视频质量。
        int     b_adaptive_mbaff; /* MBAFF+subme 0 requires non-adaptive MBAFF i.e. all field mbs */

        /* Allowed qpel MV range to stay within the picture + emulated edge pixels */
        // 在x264_t中，int mv_min[2]是一个长度为2的整型数组，用于指定运动矢量的最小值。数组中mv_min[0]表示水平方向运动矢量的最小值，mv_min[1]表示竖直方向运动矢量的最小值。运动矢量是指当前帧中像素在参考帧中对应的位置差，它用于表示像素在时域和空域的移动方向和大小。最小值的设定可以用于约束运动估计的搜索范围，从而进一步提高编码效率和视频质量。
        int     mv_min[2];
        // 用于指定运动矢量的最大值
        int     mv_max[2];
        // 在x264_t中，int mv_miny_row[3]是一个长度为3的整型数组，用于指定运动矢量的最小值。数组中mv_miny_row[0]表示水平方向上第三个亮度子块的最小值，mv_miny_row[1]表示第二个亮度子块的最小值，mv_miny_row[2]表示第一个亮度子块和所有色度子块的最小值。亮度子块和色度子块是视频编码过程中的一个概念，表示视频帧的不同部分按照亮度和色度进行的划分。在编码过程中，设定最小值可以用于约束运动估计的搜索范围，进一步提高编码效率和视频质量。
        int     mv_miny_row[3]; /* 0 == top progressive, 1 == bot progressive, 2 == interlaced */
        // 用于指定运动矢量的最大值
        int     mv_maxy_row[3];
        /* Subpel MV range for motion search.
         * same mv_min/max but includes levels' i_mv_range. */
        // 像素级的运动矢量
        int     mv_min_spel[2];
        int     mv_max_spel[2];
        int     mv_miny_spel_row[3];
        int     mv_maxy_spel_row[3];
        /* Fullpel MV range for motion search */
        /*在x264_t中，mv_limit_fpel[2][2]是一个二维的整型数组，用于指定当前帧的整像素运动估计示性运动矢量（参考帧中的位置变化量）的搜索范围。数组中的第一个维度表示运动矢量距离参考帧原点（左上角）的水平方向和竖直方向的偏移量，第二个维度表示搜索范围的左右和上下边界偏移量。例如，数组mv_limit_fpel[0][0]表示搜索范围左边界的偏移量为0（即搜索范围从参考帧原点开始），右边界的偏移量为0，上边界的偏移量为0，下边界的偏移量为0。数组中的mv_limit_fpel[0][1]表示搜索范围左边界的偏移量为0，右边界的偏移量为1，上边界的偏移量为0，下边界的偏移量为0，以此类推。设定整像素运动矢量的搜索范围可以用于限制运动估计的范围，从而进一步提高编码效率和视频质量。*/
        ALIGNED_8( int16_t mv_limit_fpel[2][2] ); /* min_x, min_y, max_x, max_y */

        int     mv_miny_fpel_row[3];
        int     mv_maxy_fpel_row[3];

        /* neighboring MBs */
        /*在x264_t中，unsigned int i_neighbour是一个无符号整型变量，用于表示某一个宏块在参考图像中的邻居的个数。在视频编码中，运动估计是一种常用的技术，它根据当前图像和之前的参考帧之间的像素差异来预测当前的图像，并生成残差（Residual）数据来描述预测误差。而宏块则是用于划分图像的编码单元，多个宏块可以组成一个视频帧。当编码程序进行预测时，通常需要访问相邻宏块的像素数据，以生成当前宏块的预测数据。由于运动估计通常是以宏块为单位进行的，因此i_neighbour用于指定当前宏块在参考图像中的邻居数，以便在预测过程中正确获取邻居宏块的像素数据。*/
        unsigned int i_neighbour;
        /*在x264_t中，unsigned int i_neighbour8[4]是一个无符号整型数组，用于指定每个宏块在参考图像中上、下、左、右四个方向的邻居宏块数。数组中的第一个元素表示当前宏块上方的邻居宏块数，第二个元素表示下方的邻居宏块数，第三个元素表示左侧的邻居宏块数，第四个元素表示右侧的邻居宏块数。宏块邻居数的设定可以用于xx设计运动估计算法，以便在预测过程中精准获取邻居宏块的像素数据，从而提高视频质量和编码效率。*/
        // 还是存储4个8x8宏块的邻居数？？
        unsigned int i_neighbour8[4];       /* neighbours of each 8x8 or 4x4 block that are available */
        // 在x264_t中，unsigned int i_neighbour4[16]是一个无符号整型数组，用于指定参考图像中16个宏块的四个邻居宏块数。这个数组的长度是16，每一个元素代表一个宏块的四个邻居宏块数，其中宏块邻居顺序从左到右，从上到下按照自然坐标顺序存储。宏块邻居数的设定可以用于设计运动估计算法，以便在预测过程中精准获取邻居宏块的像素数据，从而提高视频质量和编码效率。
        unsigned int i_neighbour4[16];      /* at the time the block is coded */
        /*在x264_t中，unsigned int i_neighbour_intra是一个无符号整型变量，用于指定当前宏块在帧内预测模式下需要使用的参考宏块邻居个数。在帧内预测模式下，当前宏块的预测数据是由左、上和左上方3个邻居宏块像素数据推断得出的。i_neighbour_intra的设定可以用于指定当前宏块模式下需要使用哪些邻居宏块，从而进一步提高编码效率和视频质量。*/
        // 用于记录帧内模式下，哪些方向有邻居宏块
        unsigned int i_neighbour_intra;     /* for constrained intra pred */
        /*在x264_t中，unsigned int i_neighbour_frame是一个无符号整型变量，用于指定当前宏块在帧间预测模式下需要使用的参考宏块邻居个数。在帧间预测模式下，当前宏块的预测数据是由参考帧中与当前宏块最相似的宏块像素数据推断得出的。i_neighbour_frame的设定可以用于指定当前宏块需要使用的参考帧中的邻居宏块个数，以便在预测过程中正确获取邻居宏块的像素数据，从而提高视频质量和编码效率。*/
        // 用于记录哪个方向有邻居宏块
        unsigned int i_neighbour_frame;     /* ignoring slice boundaries */
        // 用于指示当前宏块的邻居宏块上方的宏块类型。宏块类型是指宏块在编码过程中的分类，如帧间预测宏块、帧内预测宏块、不加编码宏块等
        int     i_mb_type_top;
        // 用于指示当前宏块的邻居宏块左侧的两个宏块的类型
        int     i_mb_type_left[2];
        // 左上
        int     i_mb_type_topleft;
        // 右上
        int     i_mb_type_topright;
        // 在x264_t中，int i_mb_prev_xy是一个整型变量，表示前一个宏块在当前宏块所处的宏块划分位置中的位置索引
        int     i_mb_prev_xy;
        // 左侧两个的索引
        int     i_mb_left_xy[2];
        // 上面的索引
        int     i_mb_top_xy;
        int     i_mb_topleft_xy;
        int     i_mb_topright_xy;
        int     i_mb_top_y;
        int     i_mb_topleft_y;
        int     i_mb_topright_y;
        // 这是x264_t结构体中的一个成员变量，它是指向x264_left_table_t类型常量的指针。x264_left_table_t是一个包含左像素预测索引值的表格，用于视频编码中的运动估计和残差编码过程。这个指针表示编码器正在使用的左像素预测表格的地址。由于它是一个常量指针，意味着它指向的内存区域是只读的，不允许对其内容进行修改。
        const x264_left_table_t *left_index_table;
        // 这是一个整型变量，表示当前宏块(macroblock)的上一个宏块的位置在图像上的水平和垂直坐标值。在视频编码中，一个宏块是视频帧的基本编码单元，包含一个16x16像素块。i_mb_top_mbpair_xy可以帮助编码器确定当前宏块的上方是否有相邻的宏块，以便进行运动估计和残差编码。这个变量的值代表着当前宏块在宏块对(mb-pair)编码模式中的位置。如果当前宏块是一个宏块对编码模式的左边宏块，则这个变量保存了它上面宏块对的右边宏块的位置。如果当前宏块是一个宏块对编码模式的右边宏块，则这个变量保存了它上面宏块对的左边宏块的位置。
        int     i_mb_top_mbpair_xy;
        /*这是一个整型变量，表示当前宏块(top-left macroblock)的分割模式。在视频编码中，一个宏块是视频帧的基本编码单元，包含一个16x16像素块。topleft_partition用于指示当前宏块是否被分割成多个子块进行编码。可能的分割模式有四个，分别是：

- 0：不分割，整个宏块直接进行编码（16x16块）；
- 1：上部分割成两个8x16的块，下部分割成两个8x16的块；
- 2：左部分割成两个16x8的块，右部分割成两个16x8的块；
- 3：宏块分成四个8x8的块。*/
        int     topleft_partition;
        // 这是一个整型变量，表示编码器在处理当前帧时是否允许使用帧内跳过(skip)编码模式。帧内跳过编码模式是一种视频编码技术，表示跳过当前宏块的编码，直接在输出视频中复制之前的图像块，从而减少编码计算量和输出码率。b_allow_skip等于1时表示编码器允许在当前帧中使用帧内跳过编码模式，反之则不允许。
        int     b_allow_skip;
        /*这是一个整型变量，用于标识当前图像是否为场编码格式，并指示解码器在解码时采用的解码模式。在场编码格式中，一帧图像被分成两个场(Field)，每个场代表一半的图像帧。解码时需要分别解码两个场合并成完整的图像。field_decoding_flag等于0表示当前图像为帧(Frame)编码格式，等于1表示当前图像为场(Field)编码格式。

如果当前图像为场编码格式，field_decoding_flag指示解码器在解码时采用的是场解码模式还是帧解码模式。在场解码模式下，解码器先解码奇数行的像素点组成的场，再解码偶数行的像素点组成的场，最后将两个场合并成完整的图像。在帧解码模式下，解码器直接解码完整的图像帧。*/
        int     field_decoding_flag;

        /**** thread synchronization ends here ****/
        /* subsequent variables are either thread-local or constant,
         * and won't be copied from one thread to another */

        /* mb table */
        /*这是一个指向无符号8位整型(unsigned 8-bit integer)数据类型的指针，用于表示数据存储区域的起始地址。这个指针通常用于指向内存缓冲区的起始位置，以方便对缓冲区内数据的操作。

在图像处理和视频编解码中，通常需要使用内存缓冲区来暂存图像数据或编码后的数据等。base指针可以指向这些数据所在的缓冲区的起始位置，从而可以方便地进行数据读取、存储和处理等操作。由于它是一个指针，我们可以通过修改它的值来改变指针所指向的数据区域。*/
        uint8_t *base;                      /* base pointer for all malloced data in this mb */
        /*这是一个指向有符号8位整型(signed 8-bit integer)数据类型的指针，用于表示某种类型的数据。在图像和视频处理中，type指针通常用于表示不同类型的图像或视频数据，以便于进行不同类型的处理。

例如，在视频编解码中，type指针通常用于表示图像中的不同块的编码类型，如帧内预测、帧间预测、运动估计等类型。通过对编码类型的区分，编码器可以对不同的块进行不同的压缩技术，从而提高压缩效率和输出码率。同样地，解码器在解码时需要知道每个块的编码类型，以恢复原始图像。

值得注意的是，由于type指针指向的是有符号整型数据，因此在使用时需要注意符号位的扩展问题。*/
        // 记录所有宏块的类型
        int8_t  *type;                      /* mb type */
        // 分割模式
        uint8_t *partition;                 /* mb partition */
        // 这是一个指向有符号8位整型(signed 8-bit integer)数据类型的指针，用于表示不同图像或视频块的量化参数(QP)，以指定它们的比特率。
        int8_t  *qp;                        /* mb qp */
        /*这是一个指向有符号16位整型(signed 16-bit integer)数据类型的指针，用于表示当前视频帧或图像块的编码块模式(Coding Block Pattern, CBP)。CBP是一种编码方式，用于指示对应视频帧或图像块中那些块已被编码，哪些块还未被编码。

通常情况下，一个视频帧或图像块被分成多个块进行编码，CBP可以用二进制数的形式表示各个块的编码状态。例如，CBP的二进制序列11001000表示1号、2号、5号和6号块已被编码，而3号、4号、7号和8号块还未被编码。CBP数值范围在0到255之间，因为一个视频帧或图像块最多可以有256个块。

因此，在编码器和解码器中，cbp指针可以指向当前视频帧或图像块的CBP值，以帮助编码器判断哪些块需要被编码、哪些元素可以被跳过，以及解码器在解码时根据CBP值确定需要解码的块。配合其它编码器和解码器的数据结构，cbp指针可以帮助实现更高效的视频编解码算法。*/
        int16_t *cbp;                       /* mb cbp: 0x0?: luma, 0x?0: chroma, 0x100: luma dc, 0x200 and 0x400: chroma dc, 0x1000 PCM (all set for PCM) */
        /*这是一个指向有符号8位整型数组的指针，该数组包含当前宏块内每个4x4像素块的帧内4x4预测模式。在视频编码中，帧内预测(Frame Intra Prediction)是一种用于压缩视频数据的技术，用于利用视频帧中已编码的相邻像素块进行预测，从而减少需要编码的像素块数量，提高压缩效率。

在帧内预测中，每个4x4像素块被编码为一个64位数据块，其中包含4x4像素块中的所有像素值，以及一个8位整型的预测模式值，范围为0~8。预测模式表示采用何种方式对当前块进行预测，常见的预测模式包括垂直、水平、DC平均等。intra4x4_pred_mode数组指向当前宏块内每个4x4像素块的预测模式值，它是一个8位整型二维数组，行数为4，列数为4。

因此，在编码器中，intra4x4_pred_mode指针可以指向当前宏块内每个4x4像素块的预测模式值，以帮助编码器在预测块内像素值时正确地选择预测模式。在解码器中，intra4x4_pred_mode指针可以帮助解码器正确地恢复索引块的像素值，并在图像重构时使用帧内预测模式进行块内像素值的恢复。*/
        int8_t  (*intra4x4_pred_mode)[8];   /* intra4x4 pred mode. for non I4x4 set to I_PRED_4x4_DC(2) */
                                            /* actually has only 7 entries; set to 8 for write-combining optimizations */
        /*这是一个指向无符号8位整型数组的指针，该数组包含多个宏块的非零像素块数。在视频编码中，无论是帧内编码还是帧间编码，宏块都是基本的编码单元。由于视频帧通常包含大量的零像素块，编码器将只对非零块进行编码，以减少帧的大小并加快编码速度。

non_zero_count数组用于指示每个宏块内的非零像素块数，它可以被认为是一个二维数组，第一维是宏块的数量，第二维是每个宏块内的16x16像素块数。由于每个4x4像素块最多可以有15个非零像素，所以16x16像素块最多可以有15x4x4=240个非零像素。 为了避免超出数组的索引范围，每个宏块内的数组长度为16x3=48，即可以存储最多48个16x16像素块的非零块数。

因此，在编码器中，non_zero_count指针可以指向宏块中每个16x16像素块的非零块数，以帮助编码器选择正确的压缩算法并提高编码效率。在解码器中，non_zero_count指针可以帮助解码器正确地恢复非零像素块，并在图像解码后使用帧内预测模式进行块内像素恢复。*/
        // 16*3:是否是一个宏块最多可以分割为16个4*4子块，一个亮度，两个色度？？
        /*
         *   | 
         * --+-------------- 
         *   | y y y y
         *   | y y y y 
         *   | y y y y 
         *   | y y y y 
         *   | u u u u
         *   | u u u u
         *   | u u u u
         *   | u u u u
         *   | v v v v
         *   | v v v v
         *   | v v v v
         *   | v v v v
         */
        uint8_t (*non_zero_count)[16*3];    /* nzc. for I_PCM set to 16 */
        // 该变量是x264编码器库中的一个指针，其数据类型为int8_t（即signed char），用于表示一帧图像中色度分量（Cb和Cr）的预测模式，例如帧间预测模式或帧内预测模式。
        int8_t  *chroma_pred_mode;          /* chroma_pred_mode. cabac only. for non intra I_PRED_CHROMA_DC(0) */
        /*在 x264_t 结构体中，int16_t (*mv[2])[2] 是用来存储运动矢量信息的数组。具体来说，其含义如下：

- mv 是一个指针数组，有 2 个元素，用于存储两个运动矢量的信息；
- 每个元素都是一个指向二维数组的指针，这个二维数组中有 2 个元素，用于存储运动矢量在 x 轴和 y 轴方向上的分量值，每个分量都是 int16_t 类型。因此，(*mv)[0] 和 (*mv)[1] 分别表示第一个运动矢量和第二个运动矢量。*/
        // 第一个2表示前向和后向？？第二个2表示x、y方向的值
        int16_t (*mv[2])[2];                /* mb mv. set to 0 for intra mb */
        /*在 x264_t 结构体中，uint8_t (*mvd[2])[8][2] 是用来存储运动矢量差信息的数组。具体来说，其含义如下：

- mvd 是一个指针数组，有 2 个元素，用于存储两个运动矢量差的信息；
- 每个元素都是一个指向三维数组的指针，这个三维数组中有 8 个元素，每个元素是一个二维数组，用于存储单个块中 8x8 个像素点的运动矢量差的 x 轴和 y 轴方向上的分量，每个分量都是 uint8_t 类型。因此，(*mvd)[i][j][0] 和 (*mvd)[i][j][1] 分别表示第 i 个块、第 j 个像素点的运动矢量差在 x 轴和 y 轴方向上的分量值。*/
        uint8_t (*mvd[2])[8][2];            /* absolute value of mb mv difference with predict, clipped to [0,33]. set to 0 if intra. cabac only */
        /*在 x264_t 结构体中，int8_t *ref[2] 是用来存储参考帧地址信息的数组。具体来说，其含义如下：

- ref 是一个指针数组，有 2 个元素，用于存储两个参考帧的地址信息；
- 每个元素都是一个指向 int8_t 类型数据的指针，这个指针可以指向某个帧数据缓存区中的指定位置，用于表示当前帧参考的该项参考帧的地址信息。在 H.264/AVC 编码中，通常为了提高编码效率和压缩比，需要对参考帧进行帧间预测编码，即利用之前编码的参考帧来对当前帧进行估计和预测。因此，ref 数组用于存储当前帧参考的参考帧地址信息，以便在解码时用于重新构建参考帧的图像数据。

在 H.264/AVC 编码中，参考帧分为前向参考帧和后向参考帧。因此，ref 数组通常用于存储前向参考帧和后向参考帧的地址信息。索引为 0 的元素表示前向参考帧的地址，索引为 1 的元素表示后向参考帧的地址。在编码和解码过程中，可以通过访问 ref 数组的不同元素来获得对应的参考帧数据。*/
        int8_t   *ref[2];                   /* mb ref. set to -1 if non used (intra or Lx only) */
        /*在 x264_t 结构体中，int16_t (*mvr[2][X264_REF_MAX*2])[2] 是用来存储参考帧运动矢量值信息的数组。具体来说，其含义如下：

- mvr 是一个三维数组，第一维大小为 2，代表前向参考帧和后向参考帧；
- 第二维大小为 X264_REF_MAX * 2，其中 X264_REF_MAX 表示参考帧的最大数量，乘以 2 是因为同一个参考帧可以有前向和后向两种预测方式；
- 第三维是一个指向二维数组的指针，这个二维数组包含 2 个元素，分别表示运动矢量在 x 轴和 y 轴上的分量值，每个分量都是 int16_t 类型。

这个三维数组用于存储当前帧中对参考帧的运动矢量值信息。其中，第一维表示存储前向参考帧和后向参考帧中的运动矢量；第二维用于存储对不同参考帧的运动矢量值信息；第三维是一个指向二维数组的指针，用于存储某个参考帧中所有块的运动矢量值信息。*/
        // 存储的参考帧的每个宏块的矢量
        // 16x16分割模式下，与每个参考帧的矢量
        int16_t (*mvr[2][X264_REF_MAX*2])[2];/* 16x16 mv for each possible ref */
        /*在 x264_t 结构体中，int8_t *skipbp 是用来存储跳过编码辅助信息的数组。具体来说，其含义如下：

- skipbp 是一个指向 int8_t 类型数据的指针，指向一个缓存区数组，用于存储需要跳过编码的宏块、块和子块的辅助信息。该数组的大小与帧中宏块数量相对应，每个元素的值表示是否跳过对应宏块的编码或解码。*/
        int8_t  *skipbp;                    /* block pattern for SKIP or DIRECT (sub)mbs. B-frames + cabac only */
        /*在x264_t中，int8_t *mb_transform_size是指当前用于转换宏块的大小，通常用于视频编解码中的块变换。具体来说，它表示宏块（MB）的大小或块大小，即在压缩图像时用于将像素块从空间域变换到频域的块大小。因此，mb_transform_size值的大小会影响图像编码/解码的质量和速度。更大的mb_transform_size可以提高压缩效率，但会增加计算成本和复杂度。*/
        int8_t  *mb_transform_size;         /* transform_size_8x8_flag of each mb */
        /*在x264_t中，uint32_t *slice_table是一个指向slice（切片）表的指针，用于存储图像被分成的切片数量和位置信息。Slice是图像分块处理的单位，每个Slice对应一块视频分割区域，通常用于提高视频编解码效率和并行处理。slice_table指向了一个包含每个Slice位置和大小信息的数组，此数组元素的数量等于Slice的数量。因此，使用slice_table可以高效地快速定位分块的位置和大小，以便对视频进行软件解码和硬件加速处理。*/
        uint32_t *slice_table;              /* sh->first_mb of the slice that the indexed mb is part of */
        /*在x264_t中，uint8_t *field是指向代表帧的上/下半部分的数组或指针。当视频被分为两个场时，每个场都只包含帧的一半，即上半场或下半场。这种分离是因为电视信号的历史原因，但现在在许多视频编码中仍在使用。此时，field指向了一个数组或指针，该数组或指针对应帧的上半部分（或下半部分）。帧的另一半则存在另一个数组或指针中。通常，在解码过程中，两个场将被合并为完整的帧。因此，field数组中存储的是图像的一半，如果要获得完整的帧，需要将两个场组合起来，以便得到完整帧的图像。*/
        uint8_t *field;

         /* buffer for weighted versions of the reference frames */
         /*在x264_t中，pixel *p_weight_buf[X264_REF_MAX]是一个指向像素权重缓冲区的指针数组。该数组的大小等于X264_REF_MAX，即参考帧的最大数量（通常为4或5）。每个p_weight_buf[i]指向一个像素权重缓冲区，该缓冲区存储参考帧的像素加权值。在图像压缩过程中，x264_t使用这些像素权重来调整参考帧的像素值，以优化压缩效果。像素权重是通过使用运动估算技术计算出来的。在编码过程中，当前宏块（MB）的像素将与参考帧的像素进行比较，以找到最佳匹配。通过使用像素权重，可以更准确地匹配参考帧的像素，并提高压缩效率。p_weight_buf数组中的每个元素包含一个像素值指针，该指针指向一个大小为MB_AREA宏的像素加权数组，其中存储了与该参考帧对应的区域的每个像素的权重值。这些像素加权值在解码时被使用，以便重新构建参考帧的像素值。*/
        pixel *p_weight_buf[X264_REF_MAX];

        /* current value */
        // 宏块类型
        int     i_type;
        // 宏块分区类型，常用的有2个（4x4和8x8），通常使用8x8区块可以更好地适应宏块中存在细节的视频片段。如果i_partition为0，则说明宏块的分区类型为4x4。
        int     i_partition;
        // 用于8x8宏块分块中每个子块的亮度和色度预估模式。i_sub_partition[0]表示左上角子块，i_sub_partition[1]表示右上角子块，i_sub_partition[2]表示左下角子块，i_sub_partition[3]表示右下角子块。每个子区块的值表示该子区块的预测模式。这些预测模式影响编码和解码过程中的多种计算和算法，以获得更好的视觉效果。
        ALIGNED_4( uint8_t i_sub_partition[4] );
        // 用于设置DCT变换的类型。如果为1，则进行8x8变换；如果为0，则进行4x4变换。8x8变换可以提高编码效率和图像质量，但需要更多计算资源和时间。
        int     b_transform_8x8;
        // 表示亮度（Y）块中零非零系数的位置，用于计算剩余编码过程中的平均值和残差差异。
        int     i_cbp_luma;
        // 表示色度（U和V）块中零非零系数的位置，与i_cbp_luma相同。
        int     i_cbp_chroma;

        // 用于提供16x16（或者宏块边长的大小）编码过程中的预测模式。通过对预测模式进行编码和解码，可以在视频编码和解码中减小数据量，从而提高包括速度和质量在内的编码性能。
        int     i_intra16x16_pred_mode;
        // 用于提供色度块中的预测模式。
        int     i_chroma_pred_mode;

        /* skip flags for i4x4 and i8x8
         * 0 = encode as normal.
         * 1 (non-RD only) = the DCT is still in h->dct, restore fdec and skip reconstruction.
         * 2 (RD only) = the DCT has since been overwritten by RD; restore that too. */
        // 在x264_t中，int i_skip_intra表示当前宏块是否跳过内部预测。在编码视频时，对于一些场景，将宏块设置为跳过内部预测可以提高压缩效率并减少计算量。如果i_skip_intra的值为1，则当前宏块会跳过内部预测，从而减少编码时间和数据量。i_skip_intra只能在帧类型为P帧或B帧时起作用（即该宏块不能是I帧），并且只能应用于预测块（参考帧已预测的块）。例如，对于一个被前一个P帧预测的宏块，可以将此标志设置为1，以跳过内部预测。这可用于高压缩的视频流或在线视频等实时流媒体。
        int i_skip_intra;
        /* skip flag for motion compensation */
        /* if we've already done MC, we don't need to do it again */
        /*在x264_t中，int b_skip_mc用于控制运动补偿是否被跳过。运动补偿（Motion Compensation, MC）是视频编解码中用于减少每个图像压缩后的数据量的一种技术。在进行帧间编码（P帧和B帧）时，当前帧与前一帧或前后帧进行比较。通过计算参考帧中相对位置上的运动向量，并用该向量对预测帧进行运动补偿，从而减少重复的图像数据。

当b_skip_mc的值为1时，运动补偿将被跳过，这意味着编码器将不会使用参考帧与当前帧进行比较，直接进行无损编码。因此，这可以用于视频序列中静态图像区域的编码，以减少编码时间和数据量。b_skip_mc只对P帧和B帧起作用，对于I帧无影响。如果当前宏块已经被跳过（在帧间编码时），则不需要再跳过运动补偿。*/
        int b_skip_mc;
        /* set to true if we are re-encoding a macroblock. */
        // 是否重新编码宏块
        int b_reencode_mb;
        // 在x264_t中，ip_offset表示压缩后的编码图像（I或P帧）相对于原始图像的偏移量。它的值是以像素为单位的，代表了编码器在对图像进行压缩时删除了多少行和列。这个值可以用来将解码后的图像与原始图像对齐，以保持图像的准确性。
        int ip_offset; /* Used by PIR to offset the quantizer of intra-refresh blocks. */
        /*在x264_t中，b_deblock_rdo是一个用于控制在B帧中是否启用循环滤波（deblocking）的参数。它是一个布尔值，当其值为1时表示启用循环滤波，当其值为0时则不启用循环滤波。循环滤波是一种技术，在视频编码中用于平滑图像边缘，以减少压缩所引入的块效应和其他视觉破坏。通过在B帧中使用循环滤波，可以进一步提高视频质量，但是会增加编码的计算复杂度。因此，通过控制b_deblock_rdo参数，可以根据具体情况来权衡视频质量和编码时间的关系。*/
        int b_deblock_rdo;
        /*在x264_t中，b_overflow是用于控制编码器B帧缓冲区溢出时采取的行为的参数。它是一个整数值，代表编码器在面对缓冲区溢出时应该执行的动作。具体来说，它的值为0时，表示当编码器的B帧缓冲区已满时，将丢弃一些最旧的B帧，然后继续编码；它的值为1时，表示当B帧缓冲区已满时，编码器应该立即停止编码，并输出已经完成的码流。这个参数主要用于控制编码器在处理长序列（如电影）时的行为，以避免因缓冲溢出导致的码流损坏或运行时错误。*/
        int b_overflow; /* If CAVLC had a level code overflow during bitstream writing. */

        struct
        {
            /* space for p_fenc and p_fdec */
#define FENC_STRIDE 16
#define FDEC_STRIDE 32
            /*在x264_t中，fenc_buf是一个用于存储编码器和解码器相关数据的一维数组。它的元素类型是像素（pixel），即一般情况下是8位无符号整数，可表示像素的灰度值或RGB颜色分量等。这个数组的大小为48*FENC_STRIDE，其中FENC_STRIDE是一个文件级别的常量，代表编码器和解码器处理的图像帧的宽度（以像素为单位）。

这个数组主要用于存储编码器和解码器的中间数据，包括用于滤波、重构和预测等操作的像素值和相关参数。这些数据在编码和解码过程中被频繁地访问和修改，因此fenc_buf需要具备高速存取和修改的能力。在x264中，fenc_buf是一个利用SIMD指令进行优化的数组，可以在不同平台上实现高效的存取和处理。*/
            /* 
             * fenc_buf yuv420格式如下 
             *   | 
             * --+-------------------------------------- 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y  
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y  
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 
             *   | U U U U U U U U V V V V V V V V 
             *   | U U U U U U U U V V V V V V V V 
             *   | U U U U U U U U V V V V V V V V 
             *   | U U U U U U U U V V V V V V V V 
             *   | U U U U U U U U V V V V V V V V 
             *   | U U U U U U U U V V V V V V V V 
             *   | U U U U U U U U V V V V V V V V 
             *   | U U U U U U U U V V V V V V V V 
             */ 
            ALIGNED_64( pixel fenc_buf[48*FENC_STRIDE] );
            /*在x264_t中，fdec_buf是一个用于存储解码器相关数据的一维数组。它的元素类型是像素（pixel），即一般情况下是8位无符号整数，可表示像素的灰度值或RGB颜色分量等。这个数组的大小为54*FDEC_STRIDE，其中FDEC_STRIDE是一个文件级别的常量，代表解码器处理的图像帧的宽度（以像素为单位）。*/
            /* 
             * fdec_buf yuv420格式如下 
             *   | 0                                                             31
             * --+---------------------------------------------------------------------------- 
             *   |                                                               y
             *   | y y y y y y y y y y y y y y y y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               y
             *   | Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y                               u
             *   | u u u u u u u u               v v v v v v v v v               u
             *   | U U U U U U U U               v V V V V V V V V               u
             *   | U U U U U U U U               v V V V V V V V V               u
             *   | U U U U U U U U               v V V V V V V V V               u
             *   | U U U U U U U U               v V V V V V V V V               u
             *   | U U U U U U U U               v V V V V V V V V               u
             *   | U U U U U U U U               v V V V V V V V V               u
             *   | U U U U U U U U               v V V V V V V V V               u
             *   | U U U U U U U U               v V V V V V V V V               u
             */ 
            ALIGNED_64( pixel fdec_buf[54*FDEC_STRIDE] );

            /* i4x4 and i8x8 backup data, for skipping the encode stage when possible */
            /*在x264_t中，i4x4_fdec_buf是一个用于存储4x4内部预测块相关数据的一维数组。它的元素类型是像素（pixel），即一般情况下是8位无符号整数，可表示像素的灰度值或RGB颜色分量等。这个数组的大小为16*16，代表4x4内部预测块的大小。

这个数组主要用于存储解码器的中间数据，包括解码器的输出像素值和相关参数。在解码过程中，解码器将对每个4x4预测块进行解码，计算其重构像素值，并将其存储在i4x4_fdec_buf中。这些数据在解码过程中被频繁地访问和修改，因此i4x4_fdec_buf需要具备高速存取和修改的能力。

需要注意的是，i4x4_fdec_buf是一个相对较小的数组，只用于存储4x4内部预测块的数据。而且，它只在4x4内部预测模式下使用，在其他情况下并不会被使用。*/
            ALIGNED_32( pixel i4x4_fdec_buf[16*16] );
            /*在x264_t中，i8x8_fdec_buf是一个用于存储8x8内部预测块相关数据的一维数组。它的元素类型是像素（pixel），即一般情况下是8位无符号整数，可表示像素的灰度值或RGB颜色分量等。这个数组的大小为16*16，代表8x8内部预测块的大小。

这个数组主要用于存储解码器的中间数据，包括解码器的输出像素值和相关参数。在解码过程中，解码器将对每个8x8预测块进行解码，计算其重构像素值，并将其存储在i8x8_fdec_buf中。这些数据在解码过程中被频繁地访问和修改，因此i8x8_fdec_buf需要具备高速存取和修改的能力。

需要注意的是，i8x8_fdec_buf是一个相对较小的数组，只用于存储8x8内部预测块的数据。而且，它只在8x8内部预测模式下使用，在其他情况下并不会被使用。此外，i8x8_fdec_buf和i4x4_fdec_buf不同，不是内部互相嵌套使用的，它们是两个独立的数组。*/
            ALIGNED_32( pixel i8x8_fdec_buf[16*16] );
            /*在x264_t中，i8x8_dct_buf是一个用于存储8x8 DCT变换系数数据的三维数组。它的元素类型是像素（pixel），即一般情况下是8位无符号整数，可表示像素的灰度值或RGB颜色分量等。这个数组的大小为3*64，代表了3个8x8块的DCT变换系数（每个8x8块有64个变换系数）。

这个数组主要用于存储编码器的中间数据，包括8x8块的残差值以及其DCT变换系数。在编码过程中，编码器将对每个8x8块进行DCT变换，并将变换系数存储在i8x8_dct_buf中。这些数据在编码过程中被频繁地访问和修改，因此i8x8_dct_buf需要具备高速存取和修改的能力。

需要注意的是，i8x8_dct_buf是一个三维数组，其中第一维代表8x8块的编号，第二维和第三维表示DCT变换系数的位置。由于每个8x8块的残差值和DCT变换系数都需要用到所以要存储3个8x8块的系数。此外，i8x8_dct_buf中存储的是经过量化和反量化处理后的DCT变换系数，而不是未经过处理的DCT系数。*/
            ALIGNED_64( dctcoef i8x8_dct_buf[3][64] );
            /*在x264_t中，i4x4_dct_buf是一个用于存储4x4 DCT变换系数数据的二维数组。它的元素类型是dctcoef，通常是16位有符号整数，用于存储DCT变换系数。这个数组的大小为15*16，代表了15个4x4块的DCT变换系数（每个4x4块有16个变换系数）。

这个数组主要用于存储编码器的中间数据，包括4x4块的残差值以及其DCT变换系数。在编码过程中，编码器将对每个4x4块进行DCT变换，并将变换系数存储在i4x4_dct_buf中。这些数据在编码过程中被频繁地访问和修改，因此i4x4_dct_buf需要具备高速存取和修改的能力。

需要注意的是，i4x4_dct_buf是一个二维数组，其中第一维代表4x4块的编号，第二维表示DCT变换系数的位置。i4x4_dct_buf中存储的是经过量化和反量化处理后的DCT变换系数，而不是未经过处理的DCT系数。另外，i4x4_dct_buf通常与i16x16_dct_buf、i8x8_dct_buf等DCT系数数组配合使用，以完成不同大小的块的DCT变换和编码。*/
            ALIGNED_64( dctcoef i4x4_dct_buf[15][16] );

            // 在x264_t中，i4x4_nnz_buf是一个用于存储4x4块非零个数的数组，i8x8_nnz_buf是一个用于存储8x8块非零个数的数组。它们的元素类型都是uint32_t，即32位无符号整数，用于存储块中DCT变换系数中非零值的个数。
            uint32_t i4x4_nnz_buf[4];
            uint32_t i8x8_nnz_buf[4];

            /* Psy trellis DCT data */
            // 8x8的dct
            ALIGNED_64( dctcoef fenc_dct8[4][64] );
            // 4x4的dct
            ALIGNED_64( dctcoef fenc_dct4[16][16] );

            /* Psy RD SATD/SA8D scores cache */
            // x264_t中的uint32_t fenc_satd_cache[32]是一个数组，它用于缓存32个宏块的SATD（Sum of Absolute Transformed Difference）值。SATD是计算编码视频中宏块之间变化的度量，它衡量了经过变换后的两个宏块之间的残差差异。这个数组可以加速编码过程中的SATD计算，提高编码效率。
            ALIGNED_64( uint32_t fenc_satd_cache[32] );
            // x264_t中的uint64_t fenc_hadamard_cache[9]是一个数组，用于缓存9个宏块的Hadamard变换值。Hadamard变换是一种数学变换，用于将有限长度的序列转换为一组正交的基向量。在视频编码中，Hadamard变换常用来计算宏块之间的残差，以便进行压缩编码。这个数组的作用就是加速编码过程中的Hadamard变换计算，提高编码效率。
            ALIGNED_16( uint64_t fenc_hadamard_cache[9] );

            // 是表示16x16宏块中每个4x4子块是否有编码残差的4位二进制整数，其中每个位代表一个4x4子块。如果该位为1，表示对应的4x4子块有编码残差，需要进一步进行编码；如果该位为0，则表示对应的4x4子块无编码残差，可以跳过。
            int i4x4_cbp;
            // 是表示16x16宏块中每个8x8子块是否有编码残差的4位二进制整数，其中每个位代表一个8x8子块。如果该位为1，表示对应的8x8子块有编码残差，需要进一步进行编码；如果该位为0，则表示对应的8x8子块无编码残差，可以跳过。i8x8_cbp是从i4x4_cbp中推导得出的。
            int i8x8_cbp;

            /* pointer over mb of the frame to be compressed */
            /*在x264编码器中，用于存储编码数据的变量之一是p_fenc，它是一个指针数组，用于存储YUV三个分量的编码数据。

pixel是x264编码器中用于存储像素数据的数据类型，一般为8位无符号整型。YUV三个分量分别代表亮度、色度（蓝色差分量）和色度（红色差分量），因此p_fenc[0]、p_fenc[1]、p_fenc[2]分别用于存储Y、U、V三个分量的编码数据。*/
            pixel *p_fenc[3]; /* y,u,v */
            /* pointer to the actual source frame, not a block copy */
            /*在 x264 编码器中，p_fenc_plane 是一个指针数组，用于存储编码数据的不同平面，也就是 YUV三个分量中的每个分量单独存储的数据。

pixel 是 x264 编码器中用于存储像素数据的数据类型，一般为 8 位无符号整型。YUV 三个分量分别代表亮度、色度（蓝色差分量）和色度（红色差分量），因此 p_fenc_plane[0]、p_fenc_plane[1]、p_fenc_plane[2] 分别用于存储 Y、U、V 三个分量的编码数据。*/
            pixel *p_fenc_plane[3];

            /* pointer over mb of the frame to be reconstructed  */
            // 指向重建帧
            pixel *p_fdec[3];

            /* pointer over mb of the references */
            // 用于表示参考帧的索引,前向和后向
            // 参考帧的数量？？
            int i_fref[2];
            /* [12]: yN, yH, yV, yHV, (NV12 ? uv : I444 ? (uN, uH, uV, uHV, vN, ...)) */
            /*x264_t是一个结构体，该结构体中有一个名为p_fref的二维数组，每个元素都是一个指向pixel类型的指针。该二维数组的大小为2*[X264_REF_MAX*2]*12，其中X264_REF_MAX表示最大参考帧数目，12表示最大帧长度。

具体来说，p_fref[0]表示前向参考帧，p_fref[1]表示后向参考帧。其中，p_fref[0][i][j]表示第i帧的第j个像素的前向参考像素值，p_fref[1][i][j]表示第i帧的第j个像素的后向参考像素值。

这个数组存储了当前帧所需的参考帧信息，可以用来进行运动估计和运动补偿等操作。*/
            // 2：前向和后向
            // 12=3*4;y、u、v每个分量占4
            // 包括yN(整点像素),yH(1/2水平内插),yV(1/2垂直内插), yHV(1/2斜对角内插)
            pixel *p_fref[2][X264_REF_MAX*2][12];
            /*这是另一个变量，表示一个长度为X264_REF_MAX*2的数组，每个元素都是一个指向pixel类型的指针。p_fref_w数组被用于编码过程中的加权预测。在加权预测中，会对参考帧进行加权，得到一个加权参考帧，以获得更好的压缩效果。p_fref_w[i]表示第i个参考帧在加权后的指针值。*/
            pixel *p_fref_w[X264_REF_MAX*2];  /* weighted fullpel luma */
            /*p_integral数组用于存储参考帧的积分图信息，以便快速地计算多种区域特征。积分图是一种数据结构，用于对图像中的像素值进行积分并快速计算像素矩形区域内的和。p_integral[0]表示前向参考帧的积分图，p_integral[1]表示后向参考帧的积分图。p_integral[i][j]表示第j个参考帧在第i个方向的积分图指针。*/
            uint16_t *p_integral[2][X264_REF_MAX];

            /* fref stride */
            /*表示一个长度为3的int类型数组。该数组用于存储图像的行跨度信息，表示每行像素数据在连续内存块中所占的字节数。具体来说，i_stride[0]表示亮度(Y)数据行跨度，i_stride[1]表示蓝色色度(Cb)数据行跨度，i_stride[2]表示红色色度(Cr)数据行跨度。

行跨度是一种优化技术，它将图像中相邻行的像素数据存储在相邻内存块中，以利用计算机内存的缓存机制，提高数据访问速度。i_stride[0]通常是图像的宽度，i_stride[1]和i_stride[2]通常是宽度的一半，因为色度数据通常是按2:1:1的比例采样的。*/
            int     i_stride[3];
        } pic;

        /* cache */
        struct
        {
            /* real intra4x4_pred_mode if I_4X4 or I_8X8, I_PRED_4x4_DC if mb available, -1 if not */
            /*x264_t是一个结构体，它包含了视频编码中的各种设置和信息。其中，intra4x4_pred_mode是一个长度为X264_SCAN8_LUMA_SIZE的int8_t数组，X264_SCAN8_LUMA_SIZE表示图像中亮度分量的4x4块数，也就是说，该数组存储了每个亮度4x4块的预测模式。*/
            /* 
             * mb.cache.intra4x4_pred_mode[]格式如下 
             *   | 
             * --+-------------- 
             *   | 0 0 0 y y y y y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             */ 
            ALIGNED_16( int8_t intra4x4_pred_mode[X264_SCAN8_LUMA_SIZE] );

            /* i_non_zero_count if available else 0x80. intentionally misaligned by 8 for asm */
            /*non_zero_count数组表示每个块中非零的系数个数，系数表示变换后的一维块中的每个数值，用于表示该块在DCT或其他变换域上的系数。在视频编码中，当一个块中的系数都为0时，可以将该块视为不需要编码，直接用零来表示，从而提高编码效率。

non_zero_count的作用是在编码过程中，根据块中的non_zero_count值来判断是否需要对该块进行编码。如果non_zero_count等于0，说明该块中的所有系数都为0，可以用零来表示，不需要进行编码。如果non_zero_count大于0，说明该块中有非零系数，需要对其进行编码。*/
            /* 
             * mb.cache.non_zero_count[]格式如下 
             *   | 
             * --+-------------- 
             *   | 0 0 0 y y y y y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 u u u u u 
             *   | 0 0 0 u U U U U 
             *   | 0 0 0 u U U U U 
             *   | 0 0 0 u U U U U 
             *   | 0 0 0 u U U U U 
             *   | 0 0 0 v v v v v 
             *   | 0 0 0 v V V V V 
             *   | 0 0 0 v V V V V 
             *   | 0 0 0 v V V V V 
             *   | 0 0 0 v V V V V 
             */  
            ALIGNED_8( uint8_t non_zero_count[X264_SCAN8_SIZE] );

            /* -1 if unused, -2 if unavailable */
            // 保存邻块的参考帧的帧号
            /* 
             * mb.cache.ref[0][]格式如下 
             *   | 
             * --+-------------- 
             *   | 0 0 0 y y y y y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             */  
            ALIGNED_4( int8_t ref[2][X264_SCAN8_LUMA_SIZE] );

            /* 0 if not available */
            // 保存邻块的矢量
            /* 
             * mb.cache.mv[0][]格式如下 
             *   | 
             * --+-------------- 
             *   | 0 0 0 y y y y y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             *   | 0 0 0 y Y Y Y Y 
             */ 
            ALIGNED_16( int16_t mv[2][X264_SCAN8_LUMA_SIZE][2] );
            ALIGNED_8( uint8_t mvd[2][X264_SCAN8_LUMA_SIZE][2] );

            /* 1 if SKIP or DIRECT. set only for B-frames + CABAC */
            ALIGNED_4( int8_t skip[X264_SCAN8_LUMA_SIZE] );

            ALIGNED_4( int16_t direct_mv[2][4][2] );
            ALIGNED_4( int8_t  direct_ref[2][4] );
            int     direct_partition;
            ALIGNED_4( int16_t pskip_mv[2] );

            /* number of neighbors (top and left) that used 8x8 dct */
            // 使用8x8的邻居宏块数目
            int     i_neighbour_transform_size;
            int     i_neighbour_skip;

            /* neighbor CBPs */
            int     i_cbp_top;
            int     i_cbp_left;

            /* extra data required for mbaff in mv prediction */
            int16_t topright_mv[2][3][2];
            int8_t  topright_ref[2][3];

            /* current mb deblock strength */
            uint8_t (*deblock_strength)[8][4];
        } cache;

        /* */
        int     i_qp;       /* current qp */
        int     i_chroma_qp;
        int     i_last_qp;  /* last qp */
        int     i_last_dqp; /* last delta qp */
        int     b_variable_qp; /* whether qp is allowed to vary per macroblock */
        int     b_lossless;
        int     b_direct_auto_read; /* take stats for --direct auto from the 2pass log */
        int     b_direct_auto_write; /* analyse direct modes, to use and/or save */

        /* lambda values */
        int     i_trellis_lambda2[2][2]; /* [luma,chroma][inter,intra] */
        int     i_psy_rd_lambda;
        int     i_chroma_lambda2_offset;

        /* B_direct and weighted prediction */
        int16_t dist_scale_factor_buf[2][2][X264_REF_MAX*2][4];
        int16_t (*dist_scale_factor)[4];
        int8_t bipred_weight_buf[2][2][X264_REF_MAX*2][4];
        int8_t (*bipred_weight)[4];
        /* maps fref1[0]'s ref indices into the current list0 */
#define map_col_to_list0(col) h->mb.map_col_to_list0[(col)+2]
        int8_t  map_col_to_list0[X264_REF_MAX+2];
        int ref_blind_dupe; /* The index of the blind reference frame duplicate. */
        int8_t deblock_ref_table[X264_REF_MAX*2+2];
#define deblock_ref_table(x) h->mb.deblock_ref_table[(x)+2]
    } mb;

    /* rate control encoding only */
    x264_ratecontrol_t *rc;

    /* stats */
    struct
    {
        /* Cumulated stats */

        /* per slice info */
        int     i_frame_count[3];
        int64_t i_frame_size[3];
        double  f_frame_qp[3];
        int     i_consecutive_bframes[X264_BFRAME_MAX+1];
        /* */
        double  f_ssd_global[3];
        double  f_psnr_average[3];
        double  f_psnr_mean_y[3];
        double  f_psnr_mean_u[3];
        double  f_psnr_mean_v[3];
        double  f_ssim_mean_y[3];
        double  f_frame_duration[3];
        /* */
        int64_t i_mb_count[3][19];
        int64_t i_mb_partition[2][17];
        int64_t i_mb_count_8x8dct[2];
        int64_t i_mb_count_ref[2][2][X264_REF_MAX*2];
        int64_t i_mb_cbp[6];
        int64_t i_mb_pred_mode[4][13];
        int64_t i_mb_field[3];
        /* */
        int     i_direct_score[2];
        int     i_direct_frames[2];
        /* num p-frames weighted */
        int     i_wpred[2];

        /* Current frame stats */
        x264_frame_stat_t frame;
    } stat;

    /* 0 = luma 4x4, 1 = luma 8x8, 2 = chroma 4x4, 3 = chroma 8x8 */
    // x264_t中的udctcoef (*nr_offset)[64]表示指向数组的指针，该数组包含了每个16x16块内所有64个DCT系数的非重建偏移量。这些偏移量用于计算DCT系数的无损变换，以便保留前一帧的细节。 nr_offset存储在x264_t结构中，是x264编码器用于视频压缩预测的一部分。
    udctcoef (*nr_offset)[64];
    // x264_t中的uint32_t (*nr_residual_sum)[64]表示指向数组的指针，该数组包含每个16x16块内所有64个像素的非重构残余和。这些值用于计算残差块的变换系数，并且通常会被用于无损视频压缩。 nr_residual_sum存储在x264_t结构中，是x264编码器用于视频压缩预测的一部分。它允许在压缩视频时保持高质量的细节和清晰度。
    uint32_t (*nr_residual_sum)[64];
    // x264_t中的uint32_t *nr_count表示指向数组的指针，该数组包含每个16x16块内非重构像素的计数。这些计数用于计算像素的平均值，并用于预测下一个帧的像素值。nr_count存储在x264_t结构中，是x264编码器用于视频压缩预测的一部分。它用于无损压缩和质量优化，以尽可能保留原始像素的细节和清晰度，同时减少压缩后视频中的损失。
    uint32_t *nr_count;

    // udctcoef nr_offset_denoise[4][64]表示包含4个16x16块的非重建偏移量数组。每个16x16块包含了64个DCT系数的偏移量，这些偏移量用于计算DCT系数的无损变换，从而保留前一帧的细节。 nr_offset_denoise存储在x264_t结构中，并用于x264编码器的视频压缩预测过程中的去噪处理。这个数组通常在编码器中用于减少图像噪声，提高视频质量并减少带宽成本，同时在保持高度压缩的同时尽可能地还原原始图像的细节。
    ALIGNED_32( udctcoef nr_offset_denoise[4][64] );
    ALIGNED_32( uint32_t nr_residual_sum_buf[2][4][64] );
    uint32_t nr_count_buf[2][4];
    // 在x264_t的源代码中，uint8_t luma2chroma_pixel[7]是一个固定长度为7的无符号8位整数数组。在视频编码中，YUV颜色空间将每个像素分解成亮度（Y）和两个色度（U和V）成分。这个数组存储从亮度值转换到色度成分的像素值的映射表。它用于处理图像中的颜色转换和降低数据量。更具体地说，它是用于将像素值从YUV420转换到YUV422和YUV444格式的过程中的一个参数。
    uint8_t luma2chroma_pixel[7]; /* Subsampled pixel size */

    /* Buffers that are allocated per-thread even in sliced threads. */
    // 在x264_t的源代码中，void *scratch_buffer是一个指向void的指针，用于指向x264_t结构体中的一个可用于存储临时数据的缓冲区。这个缓冲区是用来存储在编码过程中需要临时存储的数据，比如一些变换系数、预测模式和量化系数等。这个缓冲区的大小在不同的编码设置下可能会有所不同。在编码过程中，x264_t结构体使用这个缓冲区来存储中间结果，以提高编码效率。对于不同的场景，开发者可以根据具体需求配置这个缓冲区的大小，以提高编码效率和视频质量。
    void *scratch_buffer; /* for any temporary storage that doesn't want repeated malloc */
    void *scratch_buffer2; /* if the first one's already in use */
    // 5表示  ；3表示y/u/v
    /*在x264_t的源代码中，pixel *intra_border_backup[5][3]是一个多维指针数组，用于存储内部预测过程中需要备份的像素数据。这个数组的第一维是5，表示备份的是当前宏块上、下、左、右和左上角像素，第二维是3，表示备份的是亮度(Y)、蓝色差(Cb)和红色差(Cr)三个通道的像素数据。

在x264中，内部预测是一种用于推断当前宏块内缺失像素数据的技术。在预测过程中，需要用到当前宏块周围的像素数据进行分析和计算。然而，在计算过程中，当前宏块周围的像素数据会被修改，为了不破坏原始数据，需要将这些像素备份到intra_border_backup数组中。这样，在内部预测算法完成后，需要将备份的像素数据还原回原来的位置。

因此，intra_border_backup数组是内部预测过程中非常重要的一个数据结构，用于支持视频编码算法的正确性和质量。*/
    pixel *intra_border_backup[5][3]; /* bottom pixels of the previous mb row, used for intra prediction after the framebuffer has been deblocked */
    /* Deblock strength values are stored for each 4x4 partition. In MBAFF
     * there are four extra values that need to be stored, located in [4][i]. */
    uint8_t (*deblock_strength[2])[2][8][4];

    /* CPU functions dependents */
    /*pf[I_PRED_16x16_V ]     = x264_predict_16x16_v_c;
    pf[I_PRED_16x16_H ]     = x264_predict_16x16_h_c;
    pf[I_PRED_16x16_DC]     = x264_predict_16x16_dc_c;
    pf[I_PRED_16x16_P ]     = x264_predict_16x16_p_c;
    pf[I_PRED_16x16_DC_LEFT]= predict_16x16_dc_left_c;
    pf[I_PRED_16x16_DC_TOP ]= predict_16x16_dc_top_c;
    pf[I_PRED_16x16_DC_128 ]= predict_16x16_dc_128_c;*/
    // 在x264_t中，predict_16x16数组保存着多种预测模式的信息，可以根据不同的场景和需求选择合适的预测模式来实现图像压缩和编码。同时，这个数组也是x264_t结构体中重要的数据结构之一。
    x264_predict_t      predict_16x16[4+3];
    /*pf[I_PRED_8x8_V]      = x264_predict_8x8_v_c;
    pf[I_PRED_8x8_H]      = x264_predict_8x8_h_c;
    pf[I_PRED_8x8_DC]     = x264_predict_8x8_dc_c;
    pf[I_PRED_8x8_DDL]    = predict_8x8_ddl_c;
    pf[I_PRED_8x8_DDR]    = predict_8x8_ddr_c;
    pf[I_PRED_8x8_VR]     = predict_8x8_vr_c;
    pf[I_PRED_8x8_HD]     = predict_8x8_hd_c;
    pf[I_PRED_8x8_VL]     = predict_8x8_vl_c;
    pf[I_PRED_8x8_HU]     = predict_8x8_hu_c;
    pf[I_PRED_8x8_DC_LEFT]= predict_8x8_dc_left_c;
    pf[I_PRED_8x8_DC_TOP] = predict_8x8_dc_top_c;
    pf[I_PRED_8x8_DC_128] = predict_8x8_dc_128_c;*/
    x264_predict8x8_t   predict_8x8[9+3];
    x264_predict_t      predict_4x4[9+3];
    x264_predict_t      predict_chroma[4+3];
    x264_predict_t      predict_8x8c[4+3];
    /*pf[I_PRED_CHROMA_V ]     = x264_predict_8x16c_v_c;
    pf[I_PRED_CHROMA_H ]     = x264_predict_8x16c_h_c;
    pf[I_PRED_CHROMA_DC]     = x264_predict_8x16c_dc_c;
    pf[I_PRED_CHROMA_P ]     = x264_predict_8x16c_p_c;
    pf[I_PRED_CHROMA_DC_LEFT]= predict_8x16c_dc_left_c;
    pf[I_PRED_CHROMA_DC_TOP ]= predict_8x16c_dc_top_c;
    pf[I_PRED_CHROMA_DC_128 ]= predict_8x16c_dc_128_c;*/
    x264_predict_t      predict_8x16c[4+3];
    /*8x8预测滤波是一种特殊的预处理技术，旨在减少图像数据压缩编码后出现的伪影和噪点。在x264_t中，这个结构体的主要作用是支持编码器在8x8子块级别进行滤波处理。predict_8x8_filter成员指向一个预测滤波器函数的函数指针数组，这些函数实现了不同的8x8预测滤波算法。intra8x8_predmode_table是8x8内部预测的预测模式表，用于预测8x8子块的像素值。dst_stride成员表示目标帧中一个宏块扫描行的跨度，filter成员表示当前使用的预测滤波器类型，dst成员表示目标帧宏块的存储地址。*/
    x264_predict_8x8_filter_t predict_8x8_filter;

    // 像素相关函数。比较差异，sad，satd等
    x264_pixel_function_t pixf;
    // 运动补偿
    x264_mc_functions_t   mc;
    // 变换相关函数
    x264_dct_function_t   dctf;
    // 之字扫描相关函数
    x264_zigzag_function_t zigzagf;
    x264_zigzag_function_t zigzagf_interlaced;
    x264_zigzag_function_t zigzagf_progressive;
    // 量化相关函数
    x264_quant_function_t quantf;
    // 滤波相关函数
    x264_deblock_function_t loopf;
    // cabac 相关函数
    x264_bitstream_function_t bsf;

    x264_lookahead_t *lookahead;

#if HAVE_OPENCL
    x264_opencl_t opencl;
#endif
};

typedef struct
{
    int sad;
    int16_t mv[2];
} mvsad_t;

// included at the end because it needs x264_t
#include "macroblock.h"

static ALWAYS_INLINE int x264_predictor_roundclip( int16_t (*dst)[2], int16_t (*mvc)[2], int i_mvc, int16_t mv_limit[2][2], uint32_t pmv )
{
    int cnt = 0;
    for( int i = 0; i < i_mvc; i++ )
    {
        int mx = (mvc[i][0] + 2) >> 2;
        int my = (mvc[i][1] + 2) >> 2;
        uint32_t mv = pack16to32_mask(mx, my);
        if( !mv || mv == pmv ) continue;
        dst[cnt][0] = x264_clip3( mx, mv_limit[0][0], mv_limit[1][0] );
        dst[cnt][1] = x264_clip3( my, mv_limit[0][1], mv_limit[1][1] );
        cnt++;
    }
    return cnt;
}

//  裁减候选的运动向量，除掉那些 0 向量 或 等于 pmv (mvp) 的向量
static ALWAYS_INLINE int x264_predictor_clip( int16_t (*dst)[2], int16_t (*mvc)[2], int i_mvc, int16_t mv_limit[2][2], uint32_t pmv )
{
    int cnt = 0;
    int qpel_limit[4] = {mv_limit[0][0] << 2, mv_limit[0][1] << 2, mv_limit[1][0] << 2, mv_limit[1][1] << 2};
    for( int i = 0; i < i_mvc; i++ )
    {
        uint32_t mv = M32( mvc[i] );
        int mx = mvc[i][0];
        int my = mvc[i][1];
        if( !mv || mv == pmv ) continue;
        dst[cnt][0] = x264_clip3( mx, qpel_limit[0], qpel_limit[2] );
        dst[cnt][1] = x264_clip3( my, qpel_limit[1], qpel_limit[3] );
        cnt++;
    }
    return cnt;
}

#if ARCH_X86 || ARCH_X86_64
#include "x86/util.h"
#endif

#include "rectangle.h"

#endif
